static uint8_t *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_code(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; } 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_code(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_code(s->pc++); reg = ((modrm >> 3) & 7); mod = (modrm >> 6) & 3; rm = modrm & 7; if (mod != 3) { gen_lea_modrm(s, modrm, &reg_addr, &offset_addr); opreg = OR_TMP0; } else if (op == OP_XORL && rm == reg) { xor_zero: /* xor reg, reg optimisation */ gen_op_movl_T0_0(); s->cc_op = CC_OP_LOGICB + ot; gen_op_mov_reg_T0[ot][reg](); gen_op_update1_cc(); break; } else { opreg = rm; } gen_op_mov_TN_reg[ot][1][reg](); gen_op(s, op, ot, opreg); break; case 1: /* OP Gv, Ev */ modrm = ldub_code(s->pc++); mod = (modrm >> 6) & 3; reg = ((modrm >> 3) & 7); rm = modrm & 7; if (mod != 3) { gen_lea_modrm(s, modrm, &reg_addr, &offset_addr); gen_op_ld_T1_A0[ot + s->mem_index](); } else if (op == OP_XORL && rm == reg) { goto xor_zero; } else { gen_op_mov_TN_reg[ot][1][rm](); } gen_op(s, op, ot, reg); break; case 2: /* OP A, Iv */ val = insn_get(s, ot); gen_op_movl_T1_im(val); gen_op(s, op, ot, OR_EAX); break; } } break; case 0x80: /* GRP1 */ case 0x81: case 0x82: case 0x83: { int val; if ((b & 1) == 0) ot = OT_BYTE; else ot = dflag ? OT_LONG : OT_WORD; modrm = ldub_code(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); opreg = OR_TMP0; } else { opreg = rm + OR_EAX; } switch(b) { default: case 0x80: case 0x81: case 0x82: val = insn_get(s, ot); break; case 0x83: val = (int8_t)insn_get(s, OT_BYTE); break; } gen_op_movl_T1_im(val); gen_op(s, op, ot, opreg); } 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_code(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 + s->mem_index](); } 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 + s->mem_index](); } else { gen_op_mov_reg_T0[ot][rm](); } break; case 3: /* neg */ gen_op_negl_T0(); if (mod != 3) { gen_op_st_T0_A0[ot + s->mem_index](); } else { gen_op_mov_reg_T0[ot][rm](); } gen_op_update_neg_cc(); s->cc_op = CC_OP_SUBB + ot; break; case 4: /* mul */ switch(ot) { case OT_BYTE: gen_op_mulb_AL_T0(); s->cc_op = CC_OP_MULB; break; case OT_WORD: gen_op_mulw_AX_T0(); s->cc_op = CC_OP_MULW; break; default: case OT_LONG: gen_op_mull_EAX_T0(); s->cc_op = CC_OP_MULL; break; } break; case 5: /* imul */ switch(ot) { case OT_BYTE: gen_op_imulb_AL_T0(); s->cc_op = CC_OP_MULB; break; case OT_WORD: gen_op_imulw_AX_T0(); s->cc_op = CC_OP_MULW; break; default: case OT_LONG: gen_op_imull_EAX_T0(); s->cc_op = CC_OP_MULL; break; } break; case 6: /* div */ switch(ot) { case OT_BYTE: gen_op_divb_AL_T0(pc_start - s->cs_base); break; case OT_WORD: gen_op_divw_AX_T0(pc_start - s->cs_base); break; default: case OT_LONG: gen_op_divl_EAX_T0(pc_start - s->cs_base); break; } break; case 7: /* idiv */ switch(ot) { case OT_BYTE: gen_op_idivb_AL_T0(pc_start - s->cs_base); break; case OT_WORD: gen_op_idivw_AX_T0(pc_start - s->cs_base); break; default: case OT_LONG: gen_op_idivl_EAX_T0(pc_start - s->cs_base); 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_code(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 >= 2 && op != 3 && op != 5) gen_op_ld_T0_A0[ot + s->mem_index](); } else { gen_op_mov_TN_reg[ot][0][rm](); } switch(op) { case 0: /* inc Ev */ if (mod != 3) opreg = OR_TMP0; else opreg = rm; gen_inc(s, ot, opreg, 1); break; case 1: /* dec Ev */ if (mod != 3) opreg = OR_TMP0; else opreg = rm; gen_inc(s, ot, opreg, -1); break; case 2: /* call Ev */ /* XXX: optimize if memory (no 'and' is necessary) */ if (s->dflag == 0) gen_op_andl_T0_ffff(); next_eip = s->pc - s->cs_base; gen_op_movl_T1_im(next_eip); gen_push_T1(s); gen_op_jmp_T0(); gen_eob(s); break; case 3: /* lcall Ev */ gen_op_ld_T1_A0[ot + s->mem_index](); gen_op_addl_A0_im(1 << (ot - OT_WORD + 1)); gen_op_ldu_T0_A0[OT_WORD + s->mem_index](); do_lcall: if (s->pe && !s->vm86) { if (s->cc_op != CC_OP_DYNAMIC) gen_op_set_cc_op(s->cc_op); gen_op_jmp_im(pc_start - s->cs_base); gen_op_lcall_protected_T0_T1(dflag, s->pc - s->cs_base); } else { gen_op_lcall_real_T0_T1(dflag, s->pc - s->cs_base); } gen_eob(s); break; case 4: /* jmp Ev */ if (s->dflag == 0) gen_op_andl_T0_ffff(); gen_op_jmp_T0(); gen_eob(s); break; case 5: /* ljmp Ev */ gen_op_ld_T1_A0[ot + s->mem_index](); gen_op_addl_A0_im(1 << (ot - OT_WORD + 1)); gen_op_ldu_T0_A0[OT_WORD + s->mem_index](); do_ljmp: if (s->pe && !s->vm86) { if (s->cc_op != CC_OP_DYNAMIC) gen_op_set_cc_op(s->cc_op); gen_op_jmp_im(pc_start - s->cs_base); gen_op_ljmp_protected_T0_T1(s->pc - s->cs_base); } else { gen_op_movl_seg_T0_vm(offsetof(CPUX86State,segs[R_CS])); gen_op_movl_T0_T1(); gen_op_jmp_T0(); } gen_eob(s); 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_code(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_code(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 = (int8_t)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_MULB + ot; break; case 0x1c0: case 0x1c1: /* xadd Ev, Gv */ if ((b & 1) == 0) ot = OT_BYTE; else ot = dflag ? OT_LONG : OT_WORD; modrm = ldub_code(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(); gen_op_mov_reg_T1[ot][reg](); gen_op_mov_reg_T0[ot][rm](); } else { gen_lea_modrm(s, modrm, &reg_addr, &offset_addr); gen_op_mov_TN_reg[ot][0][reg](); gen_op_ld_T1_A0[ot + s->mem_index](); gen_op_addl_T0_T1(); gen_op_st_T0_A0[ot + s->mem_index](); gen_op_mov_reg_T1[ot][reg](); } gen_op_update2_cc(); 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_code(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 + s->mem_index](); gen_op_cmpxchg_mem_T0_T1_EAX_cc[ot + s->mem_index](); } s->cc_op = CC_OP_SUBB + ot; break; case 0x1c7: /* cmpxchg8b */ modrm = ldub_code(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); /* NOTE: order is important for pop %sp */ gen_pop_update(s); gen_op_mov_reg_T0[ot][b & 7](); 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_code(s->pc++); mod = (modrm >> 6) & 3; gen_pop_T0(s); if (mod == 3) { /* NOTE: order is important for pop %sp */ gen_pop_update(s); rm = modrm & 7; gen_op_mov_reg_T0[ot][rm](); } else { /* NOTE: order is important too for MMU exceptions */ s->popl_esp_hack = 2 << dflag; gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1); s->popl_esp_hack = 0; gen_pop_update(s); } break; case 0xc8: /* enter */ { int level; val = lduw_code(s->pc); s->pc += 2; level = ldub_code(s->pc++); gen_enter(s, val, level); } break; case 0xc9: /* leave */ /* XXX: exception not precise (ESP is updated 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 */ reg = b >> 3; gen_pop_T0(s); gen_movl_seg_T0(s, reg, pc_start - s->cs_base); gen_pop_update(s); if (reg == R_SS) { /* if reg == SS, inhibit interrupts/trace. */ /* If several instructions disable interrupts, only the _first_ does it */ if (!(s->tb->flags & HF_INHIBIT_IRQ_MASK)) gen_op_set_inhibit_irq(); s->tf = 0; } if (s->is_jmp) { gen_op_jmp_im(s->pc - s->cs_base); gen_eob(s); } break; case 0x1a1: /* pop fs */ case 0x1a9: /* pop gs */ gen_pop_T0(s); gen_movl_seg_T0(s, (b >> 3) & 7, pc_start - s->cs_base); gen_pop_update(s); if (s->is_jmp) { gen_op_jmp_im(s->pc - s->cs_base); gen_eob(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_code(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_code(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 + s->mem_index](); 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_code(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 */ modrm = ldub_code(s->pc++); reg = (modrm >> 3) & 7; if (reg >= 6 || reg == R_CS) goto illegal_op; gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0); gen_movl_seg_T0(s, reg, pc_start - s->cs_base); if (reg == R_SS) { /* if reg == SS, inhibit interrupts/trace */ /* If several instructions disable interrupts, only the _first_ does it */ if (!(s->tb->flags & HF_INHIBIT_IRQ_MASK)) gen_op_set_inhibit_irq(); s->tf = 0; } if (s->is_jmp) { gen_op_jmp_im(s->pc - s->cs_base); gen_eob(s); } break; case 0x8c: /* mov Gv, seg */ modrm = ldub_code(s->pc++); reg = (modrm >> 3) & 7; mod = (modrm >> 6) & 3; if (reg >= 6) goto illegal_op; gen_op_movl_T0_seg(reg); ot = OT_WORD; if (mod == 3 && dflag) ot = OT_LONG; 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_code(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 + s->mem_index](); } else { gen_op_ldu_T0_A0[ot + s->mem_index](); } gen_op_mov_reg_T0[d_ot][reg](); } } break; case 0x8d: /* lea */ ot = dflag ? OT_LONG : OT_WORD; modrm = ldub_code(s->pc++); mod = (modrm >> 6) & 3; if (mod == 3) goto illegal_op; 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,segs[override].base)); } } if ((b & 2) == 0) { gen_op_ld_T0_A0[ot + s->mem_index](); gen_op_mov_reg_T0[ot][R_EAX](); } else { gen_op_mov_TN_reg[ot][0][R_EAX](); gen_op_st_T0_A0[ot + s->mem_index](); } 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,segs[override].base)); } } gen_op_ldu_T0_A0[OT_BYTE + s->mem_index](); 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_code(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 + s->mem_index](); gen_op_st_T0_A0[ot + s->mem_index](); 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_code(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 + s->mem_index](); gen_op_addl_A0_im(1 << (ot - OT_WORD + 1)); /* load the segment first to handle exceptions properly */ gen_op_ldu_T0_A0[OT_WORD + s->mem_index](); gen_movl_seg_T0(s, op, pc_start - s->cs_base); /* then put the data */ gen_op_mov_reg_T1[ot][reg](); if (s->is_jmp) { gen_op_jmp_im(s->pc - s->cs_base); gen_eob(s); } 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_code(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); 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_code(s->pc++); } gen_shifti(s, op, ot, opreg, shift); } } 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_code(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 + s->mem_index](); } else { gen_op_mov_TN_reg[ot][0][rm](); } gen_op_mov_TN_reg[ot][1][reg](); if (shift) { val = ldub_code(s->pc++); val &= 0x1f; if (val) { if (mod == 3) gen_op_shiftd_T0_T1_im_cc[ot][op](val); else gen_op_shiftd_mem_T0_T1_im_cc[ot + s->mem_index][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); if (mod == 3) gen_op_shiftd_T0_T1_ECX_cc[ot][op](); else gen_op_shiftd_mem_T0_T1_ECX_cc[ot + s->mem_index][op](); s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */ } if (mod == 3) { gen_op_mov_reg_T0[ot][rm](); } break; /************************/ /* floats */ case 0xd8 ... 0xdf: if (s->flags & (HF_EM_MASK | HF_TS_MASK)) { /* if CR0.EM or CR0.TS are set, generate an FPU exception */ /* XXX: what to do if illegal op ? */ gen_exception(s, EXCP07_PREX, pc_start - s->cs_base); break; } modrm = ldub_code(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: 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 0x0c: /* fldenv mem */ gen_op_fldenv_A0(s->dflag); break; case 0x0d: /* fldcw mem */ gen_op_fldcw_A0(); break; case 0x0e: /* fnstenv mem */ gen_op_fnstenv_A0(s->dflag); break; case 0x0f: /* fnstcw mem */ gen_op_fnstcw_A0(); break; case 0x1d: /* fldt mem */ gen_op_fldt_ST0_A0(); break; case 0x1f: /* fstpt mem */ gen_op_fstt_ST0_A0(); gen_op_fpop(); break; case 0x2c: /* frstor mem */ gen_op_frstor_A0(s->dflag); break; case 0x2e: /* fnsave mem */ gen_op_fnsave_A0(s->dflag); break; case 0x2f: /* fnstsw mem */ gen_op_fnstsw_A0(); break; case 0x3c: /* fbld */ gen_op_fbld_ST0_A0(); break; case 0x3e: /* fbstp */ gen_op_fbst_ST0_A0(); gen_op_fpop(); break; case 0x3d: /* fildll */ 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 0: /* feni (287 only, just do nop here) */ break; case 1: /* fdisi (287 only, just do nop here) */ break; case 2: /* fclex */ gen_op_fclex(); break; case 3: /* fninit */ gen_op_fninit(); break; case 4: /* fsetpm (287 only, just do nop here) */ break; default: goto illegal_op; } break; case 0x1d: /* fucomi */ if (s->cc_op != CC_OP_DYNAMIC) gen_op_set_cc_op(s->cc_op); gen_op_fmov_FT0_STN(opreg); gen_op_fucomi_ST0_FT0(); s->cc_op = CC_OP_EFLAGS; break; case 0x1e: /* fcomi */ if (s->cc_op != CC_OP_DYNAMIC) gen_op_set_cc_op(s->cc_op); gen_op_fmov_FT0_STN(opreg); gen_op_fcomi_ST0_FT0(); s->cc_op = CC_OP_EFLAGS; 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; case 0x3d: /* fucomip */ if (s->cc_op != CC_OP_DYNAMIC) gen_op_set_cc_op(s->cc_op); gen_op_fmov_FT0_STN(opreg); gen_op_fucomi_ST0_FT0(); gen_op_fpop(); s->cc_op = CC_OP_EFLAGS; break; case 0x3e: /* fcomip */ if (s->cc_op != CC_OP_DYNAMIC) gen_op_set_cc_op(s->cc_op); gen_op_fmov_FT0_STN(opreg); gen_op_fcomi_ST0_FT0(); gen_op_fpop(); s->cc_op = CC_OP_EFLAGS; break; case 0x10 ... 0x13: /* fcmovxx */ case 0x18 ... 0x1b: { int op1; const static uint8_t fcmov_cc[8] = { (JCC_B << 1), (JCC_Z << 1), (JCC_BE << 1), (JCC_P << 1), }; op1 = fcmov_cc[op & 3] | ((op >> 3) & 1); gen_setcc(s, op1); gen_op_fcmov_ST0_STN_T0(opreg); } break; default: goto illegal_op; } } #ifdef USE_CODE_COPY s->tb->cflags |= CF_TB_FP_USED; #endif 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 | PREFIX_REPNZ)) { gen_repz_movs(s, ot, pc_start - s->cs_base, s->pc - s->cs_base); } else { gen_movs(s, ot); } break; case 0xaa: /* stosS */ case 0xab: if ((b & 1) == 0) ot = OT_BYTE; else ot = dflag ? OT_LONG : OT_WORD; if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) { gen_repz_stos(s, ot, pc_start - s->cs_base, s->pc - s->cs_base); } else { gen_stos(s, ot); } break; case 0xac: /* lodsS */ case 0xad: if ((b & 1) == 0) ot = OT_BYTE; else ot = dflag ? OT_LONG : OT_WORD; if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) { gen_repz_lods(s, ot, pc_start - s->cs_base, s->pc - s->cs_base); } else { gen_lods(s, ot); } break; case 0xae: /* scasS */ case 0xaf: if ((b & 1) == 0) ot = OT_BYTE; else ot = dflag ? OT_LONG : OT_WORD; if (prefixes & PREFIX_REPNZ) { gen_repz_scas(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 1); } else if (prefixes & PREFIX_REPZ) { gen_repz_scas(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 0); } else { gen_scas(s, ot); 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) { gen_repz_cmps(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 1); } else if (prefixes & PREFIX_REPZ) { gen_repz_cmps(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 0); } else { gen_cmps(s, ot); s->cc_op = CC_OP_SUBB + ot; } break; case 0x6c: /* insS */ case 0x6d: if ((b & 1) == 0) ot = OT_BYTE; else ot = dflag ? OT_LONG : OT_WORD; gen_check_io(s, ot, 1, pc_start - s->cs_base); if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) { gen_repz_ins(s, ot, pc_start - s->cs_base, s->pc - s->cs_base); } else { gen_ins(s, ot); } break; case 0x6e: /* outsS */ case 0x6f: if ((b & 1) == 0) ot = OT_BYTE; else ot = dflag ? OT_LONG : OT_WORD; gen_check_io(s, ot, 1, pc_start - s->cs_base); if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) { gen_repz_outs(s, ot, pc_start - s->cs_base, s->pc - s->cs_base); } else { gen_outs(s, ot); } break; /************************/ /* port I/O */ case 0xe4: case 0xe5: if ((b & 1) == 0) ot = OT_BYTE; else ot = dflag ? OT_LONG : OT_WORD; val = ldub_code(s->pc++); gen_op_movl_T0_im(val); gen_check_io(s, ot, 0, pc_start - s->cs_base); gen_op_in[ot](); gen_op_mov_reg_T1[ot][R_EAX](); break; case 0xe6: case 0xe7: if ((b & 1) == 0) ot = OT_BYTE; else ot = dflag ? OT_LONG : OT_WORD; val = ldub_code(s->pc++); gen_op_movl_T0_im(val); gen_check_io(s, ot, 0, pc_start - s->cs_base); gen_op_mov_TN_reg[ot][1][R_EAX](); gen_op_out[ot](); break; case 0xec: case 0xed: 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_andl_T0_ffff(); gen_check_io(s, ot, 0, pc_start - s->cs_base); gen_op_in[ot](); gen_op_mov_reg_T1[ot][R_EAX](); break; case 0xee: case 0xef: 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_andl_T0_ffff(); gen_check_io(s, ot, 0, pc_start - s->cs_base); gen_op_mov_TN_reg[ot][1][R_EAX](); gen_op_out[ot](); break; /************************/ /* control */ case 0xc2: /* ret im */ val = ldsw_code(s->pc); s->pc += 2; gen_pop_T0(s); gen_stack_update(s, val + (2 << s->dflag)); if (s->dflag == 0) gen_op_andl_T0_ffff(); gen_op_jmp_T0(); gen_eob(s); 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(); gen_eob(s); break; case 0xca: /* lret im */ val = ldsw_code(s->pc); s->pc += 2; do_lret: if (s->pe && !s->vm86) { if (s->cc_op != CC_OP_DYNAMIC) gen_op_set_cc_op(s->cc_op); gen_op_jmp_im(pc_start - s->cs_base); gen_op_lret_protected(s->dflag, val); } else { gen_stack_A0(s); /* pop offset */ gen_op_ld_T0_A0[1 + s->dflag + s->mem_index](); if (s->dflag == 0) gen_op_andl_T0_ffff(); /* NOTE: keeping EIP updated is not a problem in case of exception */ gen_op_jmp_T0(); /* pop selector */ gen_op_addl_A0_im(2 << s->dflag); gen_op_ld_T0_A0[1 + s->dflag + s->mem_index](); gen_op_movl_seg_T0_vm(offsetof(CPUX86State,segs[R_CS])); /* add stack offset */ gen_stack_update(s, val + (4 << s->dflag)); } gen_eob(s); break; case 0xcb: /* lret */ val = 0; goto do_lret; case 0xcf: /* iret */ if (!s->pe) { /* real mode */ gen_op_iret_real(s->dflag); s->cc_op = CC_OP_EFLAGS; } else if (s->vm86) { if (s->iopl != 3) { gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); } else { gen_op_iret_real(s->dflag); s->cc_op = CC_OP_EFLAGS; } } else { if (s->cc_op != CC_OP_DYNAMIC) gen_op_set_cc_op(s->cc_op); gen_op_jmp_im(pc_start - s->cs_base); gen_op_iret_protected(s->dflag, s->pc - s->cs_base); s->cc_op = CC_OP_EFLAGS; } gen_eob(s); 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_jmp(s, val); } 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); gen_op_movl_T0_im(selector); gen_op_movl_T1_im(offset); } goto do_lcall; 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_jmp(s, val); 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); gen_op_movl_T0_im(selector); gen_op_movl_T1_im(offset); } goto do_ljmp; 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_jmp(s, val); 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); break; case 0x190 ... 0x19f: /* setcc Gv */ modrm = ldub_code(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_code(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 + s->mem_index](); } 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->vm86 && s->iopl != 3) { gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); } else { if (s->cc_op != CC_OP_DYNAMIC) gen_op_set_cc_op(s->cc_op); gen_op_movl_T0_eflags(); gen_push_T0(s); } break; case 0x9d: /* popf */ if (s->vm86 && s->iopl != 3) { gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); } else { gen_pop_T0(s); if (s->cpl == 0) { if (s->dflag) { gen_op_movl_eflags_T0_cpl0(); } else { gen_op_movw_eflags_T0_cpl0(); } } else { if (s->cpl <= s->iopl) { if (s->dflag) { gen_op_movl_eflags_T0_io(); } else { gen_op_movw_eflags_T0_io(); } } else { if (s->dflag) { gen_op_movl_eflags_T0(); } else { gen_op_movw_eflags_T0(); } } } gen_pop_update(s); s->cc_op = CC_OP_EFLAGS; /* abort translation because TF flag may change */ gen_op_jmp_im(s->pc - s->cs_base); gen_eob(s); } 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_code(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 + s->mem_index](); } else { gen_op_mov_TN_reg[ot][0][rm](); } /* load shift */ val = ldub_code(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 + s->mem_index](); else gen_op_mov_reg_T0[ot][rm](); gen_op_update_bt_cc(); } 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_code(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 + s->mem_index](); } 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 + s->mem_index](); else gen_op_mov_reg_T0[ot][rm](); gen_op_update_bt_cc(); } break; case 0x1bc: /* bsf */ case 0x1bd: /* bsr */ ot = dflag ? OT_LONG : OT_WORD; modrm = ldub_code(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_code(s->pc++); gen_op_aam(val); s->cc_op = CC_OP_LOGICB; break; case 0xd5: /* aad */ val = ldub_code(s->pc++); gen_op_aad(val); s->cc_op = CC_OP_LOGICB; break; /************************/ /* misc */ case 0x90: /* nop */ /* XXX: correct lock test for all insn */ if (prefixes & PREFIX_LOCK) goto illegal_op; break; case 0x9b: /* fwait */ if ((s->flags & (HF_MP_MASK | HF_TS_MASK)) == (HF_MP_MASK | HF_TS_MASK)) { gen_exception(s, EXCP07_PREX, pc_start - s->cs_base); } else { if (s->cc_op != CC_OP_DYNAMIC) gen_op_set_cc_op(s->cc_op); gen_op_jmp_im(pc_start - s->cs_base); gen_op_fwait(); } break; case 0xcc: /* int3 */ gen_interrupt(s, EXCP03_INT3, pc_start - s->cs_base, s->pc - s->cs_base); break; case 0xcd: /* int N */ val = ldub_code(s->pc++); if (s->vm86 && s->iopl != 3) { gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); } else { gen_interrupt(s, val, pc_start - s->cs_base, s->pc - s->cs_base); } break; case 0xce: /* into */ if (s->cc_op != CC_OP_DYNAMIC) gen_op_set_cc_op(s->cc_op); gen_op_into(s->pc - s->cs_base); break; case 0xf1: /* icebp (undocumented, exits to external debugger) */ gen_debug(s, pc_start - s->cs_base); break; case 0xfa: /* cli */ if (!s->vm86) { if (s->cpl <= s->iopl) { gen_op_cli(); } else { gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); } } else { if (s->iopl == 3) { gen_op_cli(); } else { gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); } } break; case 0xfb: /* sti */ if (!s->vm86) { if (s->cpl <= s->iopl) { gen_sti: gen_op_sti(); /* interruptions are enabled only the first insn after sti */ /* If several instructions disable interrupts, only the _first_ does it */ if (!(s->tb->flags & HF_INHIBIT_IRQ_MASK)) gen_op_set_inhibit_irq(); /* give a chance to handle pending irqs */ gen_op_jmp_im(s->pc - s->cs_base); gen_eob(s); } else { gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); } } else { if (s->iopl == 3) { goto gen_sti; } else { gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); } } break; case 0x62: /* bound */ ot = dflag ? OT_LONG : OT_WORD; modrm = ldub_code(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(pc_start - s->cs_base); else gen_op_boundl(pc_start - s->cs_base); 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); gen_eob(s); break; case 0x130: /* wrmsr */ case 0x132: /* rdmsr */ if (s->cpl != 0) { gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); } else { if (b & 2) gen_op_rdmsr(); else gen_op_wrmsr(); } break; case 0x131: /* rdtsc */ gen_op_rdtsc(); break; case 0x1a2: /* cpuid */ gen_op_cpuid(); break; case 0xf4: /* hlt */ if (s->cpl != 0) { gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); } else { if (s->cc_op != CC_OP_DYNAMIC) gen_op_set_cc_op(s->cc_op); gen_op_jmp_im(s->pc - s->cs_base); gen_op_hlt(); s->is_jmp = 3; } break; case 0x100: modrm = ldub_code(s->pc++); mod = (modrm >> 6) & 3; op = (modrm >> 3) & 7; switch(op) { case 0: /* sldt */ if (!s->pe || s->vm86) goto illegal_op; gen_op_movl_T0_env(offsetof(CPUX86State,ldt.selector)); ot = OT_WORD; if (mod == 3) ot += s->dflag; gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1); break; case 2: /* lldt */ if (!s->pe || s->vm86) goto illegal_op; if (s->cpl != 0) { gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); } else { gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0); gen_op_jmp_im(pc_start - s->cs_base); gen_op_lldt_T0(); } break; case 1: /* str */ if (!s->pe || s->vm86) goto illegal_op; gen_op_movl_T0_env(offsetof(CPUX86State,tr.selector)); ot = OT_WORD; if (mod == 3) ot += s->dflag; gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1); break; case 3: /* ltr */ if (!s->pe || s->vm86) goto illegal_op; if (s->cpl != 0) { gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); } else { gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0); gen_op_jmp_im(pc_start - s->cs_base); gen_op_ltr_T0(); } break; case 4: /* verr */ case 5: /* verw */ if (!s->pe || s->vm86) goto illegal_op; gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0); if (s->cc_op != CC_OP_DYNAMIC) gen_op_set_cc_op(s->cc_op); if (op == 4) gen_op_verr(); else gen_op_verw(); s->cc_op = CC_OP_EFLAGS; break; default: goto illegal_op; } break; case 0x101: modrm = ldub_code(s->pc++); mod = (modrm >> 6) & 3; op = (modrm >> 3) & 7; switch(op) { case 0: /* sgdt */ case 1: /* sidt */ if (mod == 3) goto illegal_op; gen_lea_modrm(s, modrm, &reg_addr, &offset_addr); if (op == 0) gen_op_movl_T0_env(offsetof(CPUX86State,gdt.limit)); else gen_op_movl_T0_env(offsetof(CPUX86State,idt.limit)); gen_op_st_T0_A0[OT_WORD + s->mem_index](); gen_op_addl_A0_im(2); if (op == 0) gen_op_movl_T0_env(offsetof(CPUX86State,gdt.base)); else gen_op_movl_T0_env(offsetof(CPUX86State,idt.base)); if (!s->dflag) gen_op_andl_T0_im(0xffffff); gen_op_st_T0_A0[OT_LONG + s->mem_index](); break; case 2: /* lgdt */ case 3: /* lidt */ if (mod == 3) goto illegal_op; if (s->cpl != 0) { gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); } else { gen_lea_modrm(s, modrm, &reg_addr, &offset_addr); gen_op_ld_T1_A0[OT_WORD + s->mem_index](); gen_op_addl_A0_im(2); gen_op_ld_T0_A0[OT_LONG + s->mem_index](); if (!s->dflag) gen_op_andl_T0_im(0xffffff); if (op == 2) { gen_op_movl_env_T0(offsetof(CPUX86State,gdt.base)); gen_op_movl_env_T1(offsetof(CPUX86State,gdt.limit)); } else { gen_op_movl_env_T0(offsetof(CPUX86State,idt.base)); gen_op_movl_env_T1(offsetof(CPUX86State,idt.limit)); } } break; case 4: /* smsw */ gen_op_movl_T0_env(offsetof(CPUX86State,cr[0])); gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 1); break; case 6: /* lmsw */ if (s->cpl != 0) { gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); } else { gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0); gen_op_lmsw_T0(); gen_op_jmp_im(s->pc - s->cs_base); gen_eob(s); } break; case 7: /* invlpg */ if (s->cpl != 0) { gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); } else { if (mod == 3) goto illegal_op; gen_lea_modrm(s, modrm, &reg_addr, &offset_addr); gen_op_invlpg_A0(); gen_op_jmp_im(s->pc - s->cs_base); gen_eob(s); } break; default: goto illegal_op; } break; case 0x108: /* invd */ case 0x109: /* wbinvd */ if (s->cpl != 0) { gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); } else { /* nothing to do */ } break; case 0x63: /* arpl */ if (!s->pe || s->vm86) goto illegal_op; ot = dflag ? OT_LONG : OT_WORD; modrm = ldub_code(s->pc++); reg = (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 + s->mem_index](); } else { gen_op_mov_TN_reg[ot][0][rm](); } if (s->cc_op != CC_OP_DYNAMIC) gen_op_set_cc_op(s->cc_op); gen_op_arpl(); s->cc_op = CC_OP_EFLAGS; if (mod != 3) { gen_op_st_T0_A0[ot + s->mem_index](); } else { gen_op_mov_reg_T0[ot][rm](); } gen_op_arpl_update(); break; case 0x102: /* lar */ case 0x103: /* lsl */ if (!s->pe || s->vm86) goto illegal_op; ot = dflag ? OT_LONG : OT_WORD; modrm = ldub_code(s->pc++); reg = (modrm >> 3) & 7; gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0); gen_op_mov_TN_reg[ot][1][reg](); if (s->cc_op != CC_OP_DYNAMIC) gen_op_set_cc_op(s->cc_op); if (b == 0x102) gen_op_lar(); else gen_op_lsl(); s->cc_op = CC_OP_EFLAGS; gen_op_mov_reg_T1[ot][reg](); break; case 0x118: modrm = ldub_code(s->pc++); mod = (modrm >> 6) & 3; op = (modrm >> 3) & 7; switch(op) { case 0: /* prefetchnta */ case 1: /* prefetchnt0 */ case 2: /* prefetchnt0 */ case 3: /* prefetchnt0 */ if (mod == 3) goto illegal_op; gen_lea_modrm(s, modrm, &reg_addr, &offset_addr); /* nothing more to do */ break; default: goto illegal_op; } break; case 0x120: /* mov reg, crN */ case 0x122: /* mov crN, reg */ if (s->cpl != 0) { gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); } else { modrm = ldub_code(s->pc++); if ((modrm & 0xc0) != 0xc0) goto illegal_op; rm = modrm & 7; reg = (modrm >> 3) & 7; switch(reg) { case 0: case 2: case 3: case 4: if (b & 2) { gen_op_mov_TN_reg[OT_LONG][0][rm](); gen_op_movl_crN_T0(reg); gen_op_jmp_im(s->pc - s->cs_base); gen_eob(s); } else { gen_op_movl_T0_env(offsetof(CPUX86State,cr[reg])); gen_op_mov_reg_T0[OT_LONG][rm](); } break; default: goto illegal_op; } } break; case 0x121: /* mov reg, drN */ case 0x123: /* mov drN, reg */ if (s->cpl != 0) { gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); } else { modrm = ldub_code(s->pc++); if ((modrm & 0xc0) != 0xc0) goto illegal_op; rm = modrm & 7; reg = (modrm >> 3) & 7; /* XXX: do it dynamically with CR4.DE bit */ if (reg == 4 || reg == 5) goto illegal_op; if (b & 2) { gen_op_mov_TN_reg[OT_LONG][0][rm](); gen_op_movl_drN_T0(reg); gen_op_jmp_im(s->pc - s->cs_base); gen_eob(s); } else { gen_op_movl_T0_env(offsetof(CPUX86State,dr[reg])); gen_op_mov_reg_T0[OT_LONG][rm](); } } break; case 0x106: /* clts */ if (s->cpl != 0) { gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); } else { gen_op_clts(); /* abort block because static cpu state changed */ gen_op_jmp_im(s->pc - s->cs_base); gen_eob(s); } break; default: goto illegal_op; } /* lock generation */ if (s->prefix & PREFIX_LOCK) gen_op_unlock(); return s->pc; illegal_op: if (s->prefix & PREFIX_LOCK) gen_op_unlock(); /* XXX: ensure that no lock was generated */ gen_exception(s, EXCP06_ILLOP, pc_start - s->cs_base); return s->pc; }


static void ogg_write_pages(AVFormatContext *s, int flush) { OGGContext *ogg = s->priv_data; OGGPageList *next, *p; if (!ogg->page_list) return; for (p = ogg->page_list; p; ) { OGGStreamContext *oggstream = s->streams[p->page.stream_index]->priv_data; if (oggstream->page_count < 2 && !flush) break; ogg_write_page(s, &p->page, flush && oggstream->page_count == 1 ? 4 : 0); // eos next = p->next; av_freep(&p); p = next; } ogg->page_list = p; }


static void get_lag(float *buf, const float *new, LongTermPrediction *ltp) { int i, j, lag, max_corr = 0; float max_ratio; for (i = 0; i < 2048; i++) { float corr, s0 = 0.0f, s1 = 0.0f; const int start = FFMAX(0, i - 1024); for (j = start; j < 2048; j++) { const int idx = j - i + 1024; s0 += new[j]*buf[idx]; s1 += buf[idx]*buf[idx]; } corr = s1 > 0.0f ? s0/sqrt(s1) : 0.0f; if (corr > max_corr) { max_corr = corr; lag = i; max_ratio = corr/(2048-start); } } ltp->lag = FFMAX(av_clip_uintp2(lag, 11), 0); ltp->coef_idx = quant_array_idx(max_ratio, ltp_coef, 8); ltp->coef = ltp_coef[ltp->coef_idx]; }


static void memory_region_dispatch_write(MemoryRegion *mr, hwaddr addr, uint64_t data, unsigned size) { if (!memory_region_access_valid(mr, addr, size, true)) { return; /* FIXME: better signalling */ } adjust_endianness(mr, &data, size); if (!mr->ops->write) { mr->ops->old_mmio.write[bitops_ffsl(size)](mr->opaque, addr, data); return; } /* FIXME: support unaligned access */ access_with_adjusted_size(addr, &data, size, mr->ops->impl.min_access_size, mr->ops->impl.max_access_size, memory_region_write_accessor, mr); }


int do_drive_del(Monitor *mon, const QDict *qdict, QObject **ret_data) { const char *id = qdict_get_str(qdict, "id"); BlockDriverState *bs; BlockDriverState **ptr; Property *prop; bs = bdrv_find(id); if (!bs) { qerror_report(QERR_DEVICE_NOT_FOUND, id); return -1; } if (bdrv_in_use(bs)) { qerror_report(QERR_DEVICE_IN_USE, id); return -1; } /* quiesce block driver; prevent further io */ qemu_aio_flush(); bdrv_flush(bs); bdrv_close(bs); /* clean up guest state from pointing to host resource by * finding and removing DeviceState "drive" property */ if (bs->peer) { for (prop = bs->peer->info->props; prop && prop->name; prop++) { if (prop->info->type == PROP_TYPE_DRIVE) { ptr = qdev_get_prop_ptr(bs->peer, prop); if (*ptr == bs) { bdrv_detach(bs, bs->peer); *ptr = NULL; break; } } } } /* clean up host side */ drive_uninit(drive_get_by_blockdev(bs)); return 0; }


void error_setg_file_open(Error **errp, int os_errno, const char *filename) { error_setg_errno(errp, os_errno, "Could not open '%s'", filename); }


int ff_hevc_decode_short_term_rps(GetBitContext *gb, AVCodecContext *avctx, ShortTermRPS *rps, const HEVCSPS *sps, int is_slice_header) { uint8_t rps_predict = 0; int delta_poc; int k0 = 0; int k1 = 0; int k = 0; int i; if (rps != sps->st_rps && sps->nb_st_rps) rps_predict = get_bits1(gb); if (rps_predict) { const ShortTermRPS *rps_ridx; int delta_rps; unsigned abs_delta_rps; uint8_t use_delta_flag = 0; uint8_t delta_rps_sign; if (is_slice_header) { unsigned int delta_idx = get_ue_golomb_long(gb) + 1; if (delta_idx > sps->nb_st_rps) { "Invalid value of delta_idx in slice header RPS: %d > %d.\n", delta_idx, sps->nb_st_rps); rps_ridx = &sps->st_rps[sps->nb_st_rps - delta_idx]; rps->rps_idx_num_delta_pocs = rps_ridx->num_delta_pocs; } else rps_ridx = &sps->st_rps[rps - sps->st_rps - 1]; delta_rps_sign = get_bits1(gb); abs_delta_rps = get_ue_golomb_long(gb) + 1; if (abs_delta_rps < 1 || abs_delta_rps > 32768) { "Invalid value of abs_delta_rps: %d\n", abs_delta_rps); delta_rps = (1 - (delta_rps_sign << 1)) * abs_delta_rps; for (i = 0; i <= rps_ridx->num_delta_pocs; i++) { int used = rps->used[k] = get_bits1(gb); if (!used) use_delta_flag = get_bits1(gb); if (used || use_delta_flag) { if (i < rps_ridx->num_delta_pocs) delta_poc = delta_rps + rps_ridx->delta_poc[i]; else delta_poc = delta_rps; rps->delta_poc[k] = delta_poc; if (delta_poc < 0) k0++; else k1++; k++; rps->num_delta_pocs = k; rps->num_negative_pics = k0; // sort in increasing order (smallest first) if (rps->num_delta_pocs != 0) { int used, tmp; for (i = 1; i < rps->num_delta_pocs; i++) { delta_poc = rps->delta_poc[i]; used = rps->used[i]; for (k = i - 1; k >= 0; k--) { tmp = rps->delta_poc[k]; if (delta_poc < tmp) { rps->delta_poc[k + 1] = tmp; rps->used[k + 1] = rps->used[k]; rps->delta_poc[k] = delta_poc; rps->used[k] = used; if ((rps->num_negative_pics >> 1) != 0) { int used; k = rps->num_negative_pics - 1; // flip the negative values to largest first for (i = 0; i < rps->num_negative_pics >> 1; i++) { delta_poc = rps->delta_poc[i]; used = rps->used[i]; rps->delta_poc[i] = rps->delta_poc[k]; rps->used[i] = rps->used[k]; rps->delta_poc[k] = delta_poc; rps->used[k] = used; k--; } else { unsigned int prev, nb_positive_pics; rps->num_negative_pics = get_ue_golomb_long(gb); nb_positive_pics = get_ue_golomb_long(gb); if (rps->num_negative_pics >= HEVC_MAX_REFS || nb_positive_pics >= HEVC_MAX_REFS) { av_log(avctx, AV_LOG_ERROR, "Too many refs in a short term RPS.\n"); rps->num_delta_pocs = rps->num_negative_pics + nb_positive_pics; if (rps->num_delta_pocs) { prev = 0; for (i = 0; i < rps->num_negative_pics; i++) { delta_poc = get_ue_golomb_long(gb) + 1; prev -= delta_poc; rps->delta_poc[i] = prev; rps->used[i] = get_bits1(gb); prev = 0; for (i = 0; i < nb_positive_pics; i++) { delta_poc = get_ue_golomb_long(gb) + 1; prev += delta_poc; rps->delta_poc[rps->num_negative_pics + i] = prev; rps->used[rps->num_negative_pics + i] = get_bits1(gb); return 0;


static int qcow_check(BlockDriverState *bs) { return qcow2_check_refcounts(bs); }


static void pl061_save(QEMUFile *f, void *opaque) { pl061_state *s = (pl061_state *)opaque; qemu_put_be32(f, s->locked); qemu_put_be32(f, s->data); qemu_put_be32(f, s->old_data); qemu_put_be32(f, s->dir); qemu_put_be32(f, s->isense); qemu_put_be32(f, s->ibe); qemu_put_be32(f, s->iev); qemu_put_be32(f, s->im); qemu_put_be32(f, s->istate); qemu_put_be32(f, s->afsel); qemu_put_be32(f, s->dr2r); qemu_put_be32(f, s->dr4r); qemu_put_be32(f, s->dr8r); qemu_put_be32(f, s->odr); qemu_put_be32(f, s->pur); qemu_put_be32(f, s->pdr); qemu_put_be32(f, s->slr); qemu_put_be32(f, s->den); qemu_put_be32(f, s->cr); qemu_put_be32(f, s->float_high); }


void cpu_reset(CPUSPARCState *env) { tlb_flush(env, 1); env->cwp = 0; env->wim = 1; env->regwptr = env->regbase + (env->cwp * 16); #if defined(CONFIG_USER_ONLY) env->user_mode_only = 1; #ifdef TARGET_SPARC64 env->cleanwin = env->nwindows - 2; env->cansave = env->nwindows - 2; env->pstate = PS_RMO | PS_PEF | PS_IE; env->asi = 0x82; // Primary no-fault #endif #else env->psret = 0; env->psrs = 1; env->psrps = 1; #ifdef TARGET_SPARC64 env->pstate = PS_PRIV; env->hpstate = HS_PRIV; env->pc = 0x1fff0000020ULL; // XXX should be different for system_reset env->tsptr = &env->ts[env->tl]; #else env->pc = 0; env->mmuregs[0] &= ~(MMU_E | MMU_NF); env->mmuregs[0] |= env->mmu_bm; #endif env->npc = env->pc + 4; #endif }


static void glib_select_poll(fd_set *rfds, fd_set *wfds, fd_set *xfds, bool err) { GMainContext *context = g_main_context_default(); if (!err) { int i; for (i = 0; i < n_poll_fds; i++) { GPollFD *p = &poll_fds[i]; if ((p->events & G_IO_IN) && FD_ISSET(p->fd, rfds)) { p->revents |= G_IO_IN; } if ((p->events & G_IO_OUT) && FD_ISSET(p->fd, wfds)) { p->revents |= G_IO_OUT; } if ((p->events & G_IO_ERR) && FD_ISSET(p->fd, xfds)) { p->revents |= G_IO_ERR; } } } if (g_main_context_check(context, max_priority, poll_fds, n_poll_fds)) { g_main_context_dispatch(context); } }


static void set_lcd_pixel(musicpal_lcd_state *s, int x, int y, int col) { int dx, dy; for (dy = 0; dy < 3; dy++) for (dx = 0; dx < 3; dx++) { s->ds->data[(x*3 + dx + (y*3 + dy) * 128*3) * 4 + 0] = scale_lcd_color(col); s->ds->data[(x*3 + dx + (y*3 + dy) * 128*3) * 4 + 1] = scale_lcd_color(col >> 8); s->ds->data[(x*3 + dx + (y*3 + dy) * 128*3) * 4 + 2] = scale_lcd_color(col >> 16); } }


static inline uint32_t celt_icwrsi(uint32_t N, const int *y) { int i, idx = 0, sum = 0; for (i = N - 1; i >= 0; i--) { const uint32_t i_s = CELT_PVQ_U(N - i, sum + FFABS(y[i]) + 1); idx += CELT_PVQ_U(N - i, sum) + (y[i] < 0)*i_s; sum += FFABS(y[i]); } return idx; }


static void test_qemu_strtoul_hex(void) { const char *str = "0123"; char f = 'X'; const char *endptr = &f; unsigned long res = 999; int err; err = qemu_strtoul(str, &endptr, 16, &res); g_assert_cmpint(err, ==, 0); g_assert_cmpint(res, ==, 0x123); g_assert(endptr == str + strlen(str)); str = "0x123"; res = 999; endptr = &f; err = qemu_strtoul(str, &endptr, 0, &res); g_assert_cmpint(err, ==, 0); g_assert_cmpint(res, ==, 0x123); g_assert(endptr == str + strlen(str)); }


static void mvp_init (CPUMIPSState *env, const mips_def_t *def) { env->mvp = qemu_mallocz(sizeof(CPUMIPSMVPContext)); /* MVPConf1 implemented, TLB sharable, no gating storage support, programmable cache partitioning implemented, number of allocatable and sharable TLB entries, MVP has allocatable TCs, 2 VPEs implemented, 5 TCs implemented. */ env->mvp->CP0_MVPConf0 = (1 << CP0MVPC0_M) | (1 << CP0MVPC0_TLBS) | (0 << CP0MVPC0_GS) | (1 << CP0MVPC0_PCP) | // TODO: actually do 2 VPEs. // (1 << CP0MVPC0_TCA) | (0x1 << CP0MVPC0_PVPE) | // (0x04 << CP0MVPC0_PTC); (1 << CP0MVPC0_TCA) | (0x0 << CP0MVPC0_PVPE) | (0x04 << CP0MVPC0_PTC); /* Usermode has no TLB support */ if (!env->user_mode_only) env->mvp->CP0_MVPConf0 |= (env->tlb->nb_tlb << CP0MVPC0_PTLBE); /* Allocatable CP1 have media extensions, allocatable CP1 have FP support, no UDI implemented, no CP2 implemented, 1 CP1 implemented. */ env->mvp->CP0_MVPConf1 = (1 << CP0MVPC1_CIM) | (1 << CP0MVPC1_CIF) | (0x0 << CP0MVPC1_PCX) | (0x0 << CP0MVPC1_PCP2) | (0x1 << CP0MVPC1_PCP1); }


static void i440fx_pcihost_get_pci_hole64_start(Object *obj, Visitor *v, const char *name, void *opaque, Error **errp) { PCIHostState *h = PCI_HOST_BRIDGE(obj); Range w64; pci_bus_get_w64_range(h->bus, &w64); visit_type_uint64(v, name, &w64.begin, errp); }


static void spapr_phb_remove_pci_device(sPAPRDRConnector *drc, sPAPRPHBState *phb, PCIDevice *pdev, Error **errp) { sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); drck->detach(drc, DEVICE(pdev), spapr_phb_remove_pci_device_cb, phb, errp); }


static int vmdk_parse_extents(const char *desc, BlockDriverState *bs, const char *desc_file_path, Error **errp) { int ret; char access[11]; char type[11]; char fname[512]; const char *p = desc; int64_t sectors = 0; int64_t flat_offset; char extent_path[PATH_MAX]; BlockDriverState *extent_file; BDRVVmdkState *s = bs->opaque; VmdkExtent *extent; while (*p) { /* parse extent line: * RW [size in sectors] FLAT "file-name.vmdk" OFFSET * or * RW [size in sectors] SPARSE "file-name.vmdk" */ flat_offset = -1; ret = sscanf(p, "%10s %" SCNd64 " %10s \"%511[^\n\r\"]\" %" SCNd64, access, &sectors, type, fname, &flat_offset); if (ret < 4 || strcmp(access, "RW")) { goto next_line; } else if (!strcmp(type, "FLAT")) { if (ret != 5 || flat_offset < 0) { error_setg(errp, "Invalid extent lines: \n%s", p); return -EINVAL; } } else if (!strcmp(type, "VMFS")) { flat_offset = 0; } else if (ret != 4) { error_setg(errp, "Invalid extent lines: \n%s", p); return -EINVAL; } if (sectors <= 0 || (strcmp(type, "FLAT") && strcmp(type, "SPARSE") && strcmp(type, "VMFS") && strcmp(type, "VMFSSPARSE")) || (strcmp(access, "RW"))) { goto next_line; } path_combine(extent_path, sizeof(extent_path), desc_file_path, fname); ret = bdrv_file_open(&extent_file, extent_path, NULL, bs->open_flags, errp); if (ret) { return ret; } /* save to extents array */ if (!strcmp(type, "FLAT") || !strcmp(type, "VMFS")) { /* FLAT extent */ ret = vmdk_add_extent(bs, extent_file, true, sectors, 0, 0, 0, 0, 0, &extent, errp); if (ret < 0) { return ret; } extent->flat_start_offset = flat_offset << 9; } else if (!strcmp(type, "SPARSE") || !strcmp(type, "VMFSSPARSE")) { /* SPARSE extent and VMFSSPARSE extent are both "COWD" sparse file*/ ret = vmdk_open_sparse(bs, extent_file, bs->open_flags, errp); if (ret) { bdrv_unref(extent_file); return ret; } extent = &s->extents[s->num_extents - 1]; } else { error_setg(errp, "Unsupported extent type '%s'", type); return -ENOTSUP; } extent->type = g_strdup(type); next_line: /* move to next line */ while (*p) { if (*p == '\n') { p++; break; } p++; } } return 0; }


void bdrv_release_named_dirty_bitmaps(BlockDriverState *bs) { bdrv_do_release_matching_dirty_bitmap(bs, NULL, true); }


int kvmppc_put_books_sregs(PowerPCCPU *cpu) { CPUPPCState *env = &cpu->env; struct kvm_sregs sregs; int i; sregs.pvr = env->spr[SPR_PVR]; sregs.u.s.sdr1 = env->spr[SPR_SDR1]; /* Sync SLB */ #ifdef TARGET_PPC64 for (i = 0; i < ARRAY_SIZE(env->slb); i++) { sregs.u.s.ppc64.slb[i].slbe = env->slb[i].esid; if (env->slb[i].esid & SLB_ESID_V) { sregs.u.s.ppc64.slb[i].slbe |= i; } sregs.u.s.ppc64.slb[i].slbv = env->slb[i].vsid; } #endif /* Sync SRs */ for (i = 0; i < 16; i++) { sregs.u.s.ppc32.sr[i] = env->sr[i]; } /* Sync BATs */ for (i = 0; i < 8; i++) { /* Beware. We have to swap upper and lower bits here */ sregs.u.s.ppc32.dbat[i] = ((uint64_t)env->DBAT[0][i] << 32) | env->DBAT[1][i]; sregs.u.s.ppc32.ibat[i] = ((uint64_t)env->IBAT[0][i] << 32) | env->IBAT[1][i]; } return kvm_vcpu_ioctl(CPU(cpu), KVM_SET_SREGS, &sregs); }


static void gen_brcond(DisasContext *dc, TCGCond cond, TCGv_i32 t0, TCGv_i32 t1, uint32_t offset) { int label = gen_new_label(); gen_advance_ccount(dc); tcg_gen_brcond_i32(cond, t0, t1, label); gen_jumpi_check_loop_end(dc, 0); gen_set_label(label); gen_jumpi(dc, dc->pc + offset, 1); }


static bool net_tx_pkt_rebuild_payload(struct NetTxPkt *pkt) { size_t payload_len = iov_size(pkt->raw, pkt->raw_frags) - pkt->hdr_len; pkt->payload_frags = iov_copy(&pkt->vec[NET_TX_PKT_PL_START_FRAG], pkt->max_payload_frags, pkt->raw, pkt->raw_frags, pkt->hdr_len, payload_len); if (pkt->payload_frags != (uint32_t) -1) { pkt->payload_len = payload_len; return true; } else { return false; } }


static void omap_pin_cfg_write(void *opaque, target_phys_addr_t addr, uint64_t value, unsigned size) { struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque; uint32_t diff; if (size != 4) { return omap_badwidth_write32(opaque, addr, value); } switch (addr) { case 0x00: /* FUNC_MUX_CTRL_0 */ diff = s->func_mux_ctrl[addr >> 2] ^ value; s->func_mux_ctrl[addr >> 2] = value; omap_pin_funcmux0_update(s, diff, value); return; case 0x04: /* FUNC_MUX_CTRL_1 */ diff = s->func_mux_ctrl[addr >> 2] ^ value; s->func_mux_ctrl[addr >> 2] = value; omap_pin_funcmux1_update(s, diff, value); return; case 0x08: /* FUNC_MUX_CTRL_2 */ s->func_mux_ctrl[addr >> 2] = value; return; case 0x0c: /* COMP_MODE_CTRL_0 */ s->comp_mode_ctrl[0] = value; s->compat1509 = (value != 0x0000eaef); omap_pin_funcmux0_update(s, ~0, s->func_mux_ctrl[0]); omap_pin_funcmux1_update(s, ~0, s->func_mux_ctrl[1]); return; case 0x10: /* FUNC_MUX_CTRL_3 */ case 0x14: /* FUNC_MUX_CTRL_4 */ case 0x18: /* FUNC_MUX_CTRL_5 */ case 0x1c: /* FUNC_MUX_CTRL_6 */ case 0x20: /* FUNC_MUX_CTRL_7 */ case 0x24: /* FUNC_MUX_CTRL_8 */ case 0x28: /* FUNC_MUX_CTRL_9 */ case 0x2c: /* FUNC_MUX_CTRL_A */ case 0x30: /* FUNC_MUX_CTRL_B */ case 0x34: /* FUNC_MUX_CTRL_C */ case 0x38: /* FUNC_MUX_CTRL_D */ s->func_mux_ctrl[(addr >> 2) - 1] = value; return; case 0x40: /* PULL_DWN_CTRL_0 */ case 0x44: /* PULL_DWN_CTRL_1 */ case 0x48: /* PULL_DWN_CTRL_2 */ case 0x4c: /* PULL_DWN_CTRL_3 */ s->pull_dwn_ctrl[(addr & 0xf) >> 2] = value; return; case 0x50: /* GATE_INH_CTRL_0 */ s->gate_inh_ctrl[0] = value; return; case 0x60: /* VOLTAGE_CTRL_0 */ s->voltage_ctrl[0] = value; return; case 0x70: /* TEST_DBG_CTRL_0 */ s->test_dbg_ctrl[0] = value; return; case 0x80: /* MOD_CONF_CTRL_0 */ diff = s->mod_conf_ctrl[0] ^ value; s->mod_conf_ctrl[0] = value; omap_pin_modconf1_update(s, diff, value); return; default: OMAP_BAD_REG(addr); } }


static USBDevice *usb_serial_init(USBBus *bus, const char *filename) { USBDevice *dev; Chardev *cdrv; char label[32]; static int index; while (*filename && *filename != ':') { const char *p; if (strstart(filename, "vendorid=", &p)) { error_report("vendorid is not supported anymore"); return NULL; } else if (strstart(filename, "productid=", &p)) { error_report("productid is not supported anymore"); return NULL; } else { error_report("unrecognized serial USB option %s", filename); return NULL; } while(*filename == ',') filename++; } if (!*filename) { error_report("character device specification needed"); return NULL; } filename++; snprintf(label, sizeof(label), "usbserial%d", index++); cdrv = qemu_chr_new(label, filename); if (!cdrv) return NULL; dev = usb_create(bus, "usb-serial"); qdev_prop_set_chr(&dev->qdev, "chardev", cdrv); return dev; }


static void virtio_ccw_notify(DeviceState *d, uint16_t vector) { VirtioCcwDevice *dev = to_virtio_ccw_dev_fast(d); SubchDev *sch = dev->sch; uint64_t indicators; if (vector >= 128) { return; } if (vector < VIRTIO_PCI_QUEUE_MAX) { if (!dev->indicators) { return; } if (sch->thinint_active) { /* * In the adapter interrupt case, indicators points to a * memory area that may be (way) larger than 64 bit and * ind_bit indicates the start of the indicators in a big * endian notation. */ uint64_t ind_bit = dev->routes.adapter.ind_offset; virtio_set_ind_atomic(sch, dev->indicators->addr + (ind_bit + vector) / 8, 0x80 >> ((ind_bit + vector) % 8)); if (!virtio_set_ind_atomic(sch, dev->summary_indicator->addr, 0x01)) { css_adapter_interrupt(dev->thinint_isc); } } else { indicators = address_space_ldq(&address_space_memory, dev->indicators->addr, MEMTXATTRS_UNSPECIFIED, NULL); indicators |= 1ULL << vector; address_space_stq(&address_space_memory, dev->indicators->addr, indicators, MEMTXATTRS_UNSPECIFIED, NULL); css_conditional_io_interrupt(sch); } } else { if (!dev->indicators2) { return; } vector = 0; indicators = address_space_ldq(&address_space_memory, dev->indicators2->addr, MEMTXATTRS_UNSPECIFIED, NULL); indicators |= 1ULL << vector; address_space_stq(&address_space_memory, dev->indicators2->addr, indicators, MEMTXATTRS_UNSPECIFIED, NULL); css_conditional_io_interrupt(sch); } }


void cpu_x86_load_seg(CPUX86State *s, int seg_reg, int selector) { CPUX86State *saved_env; saved_env = env; env = s; if (env->eflags & VM_MASK) { SegmentCache *sc; selector &= 0xffff; sc = &env->seg_cache[seg_reg]; /* NOTE: in VM86 mode, limit and seg_32bit are never reloaded, so we must load them here */ sc->base = (void *)(selector << 4); sc->limit = 0xffff; sc->seg_32bit = 0; env->segs[seg_reg] = selector; } else { load_seg(seg_reg, selector, 0); } env = saved_env; }


static char *sysbus_get_fw_dev_path(DeviceState *dev) { SysBusDevice *s = sysbus_from_qdev(dev); char path[40]; int off; off = snprintf(path, sizeof(path), "%s", qdev_fw_name(dev)); if (s->num_mmio) { snprintf(path + off, sizeof(path) - off, "@"TARGET_FMT_plx, s->mmio[0].addr); } else if (s->num_pio) { snprintf(path + off, sizeof(path) - off, "@i%04x", s->pio[0]); } return strdup(path); }


void hmp_info_memory_devices(Monitor *mon, const QDict *qdict) { Error *err = NULL; MemoryDeviceInfoList *info_list = qmp_query_memory_devices(&err); MemoryDeviceInfoList *info; MemoryDeviceInfo *value; PCDIMMDeviceInfo *di; for (info = info_list; info; info = info->next) { value = info->value; if (value) { switch (value->kind) { case MEMORY_DEVICE_INFO_KIND_DIMM: di = value->dimm; monitor_printf(mon, "Memory device [%s]: \"%s\"\n", MemoryDeviceInfoKind_lookup[value->kind], di->id ? di->id : ""); monitor_printf(mon, " addr: 0x%" PRIx64 "\n", di->addr); monitor_printf(mon, " slot: %" PRId64 "\n", di->slot); monitor_printf(mon, " node: %" PRId64 "\n", di->node); monitor_printf(mon, " size: %" PRIu64 "\n", di->size); monitor_printf(mon, " memdev: %s\n", di->memdev); monitor_printf(mon, " hotplugged: %s\n", di->hotplugged ? "true" : "false"); monitor_printf(mon, " hotpluggable: %s\n", di->hotpluggable ? "true" : "false"); break; default: break; } } } qapi_free_MemoryDeviceInfoList(info_list); }


static void v9fs_synth_seekdir(FsContext *ctx, V9fsFidOpenState *fs, off_t off) { V9fsSynthOpenState *synth_open = fs->private; synth_open->offset = off; }


static struct vm_area_struct *vma_first(const struct mm_struct *mm) { return (TAILQ_FIRST(&mm->mm_mmap)); }


static int dnxhd_mb_var_thread(AVCodecContext *avctx, void *arg, int jobnr, int threadnr) { DNXHDEncContext *ctx = avctx->priv_data; int mb_y = jobnr, mb_x; ctx = ctx->thread[threadnr]; if (ctx->cid_table->bit_depth == 8) { uint8_t *pix = ctx->thread[0]->src[0] + ((mb_y<<4) * ctx->m.linesize); for (mb_x = 0; mb_x < ctx->m.mb_width; ++mb_x, pix += 16) { unsigned mb = mb_y * ctx->m.mb_width + mb_x; int sum = ctx->m.dsp.pix_sum(pix, ctx->m.linesize); int varc = (ctx->m.dsp.pix_norm1(pix, ctx->m.linesize) - (((unsigned)(sum*sum))>>8)+128)>>8; ctx->mb_cmp[mb].value = varc; ctx->mb_cmp[mb].mb = mb; } } else { // 10-bit int const linesize = ctx->m.linesize >> 1; for (mb_x = 0; mb_x < ctx->m.mb_width; ++mb_x) { uint16_t *pix = (uint16_t*)ctx->thread[0]->src[0] + ((mb_y << 4) * linesize) + (mb_x << 4); unsigned mb = mb_y * ctx->m.mb_width + mb_x; int sum = 0; int sqsum = 0; int mean, sqmean; // Macroblocks are 16x16 pixels, unlike DCT blocks which are 8x8. for (int i = 0; i < 16; ++i) { for (int j = 0; j < 16; ++j) { // Turn 16-bit pixels into 10-bit ones. int const sample = (unsigned)pix[j] >> 6; sum += sample; sqsum += sample * sample; // 2^10 * 2^10 * 16 * 16 = 2^28, which is less than INT_MAX } pix += linesize; } mean = sum >> 8; // 16*16 == 2^8 sqmean = sqsum >> 8; ctx->mb_cmp[mb].value = sqmean - mean * mean; ctx->mb_cmp[mb].mb = mb; } } return 0; }


static void xan_wc3_decode_frame(XanContext *s) { int width = s->avctx->width; int height = s->avctx->height; int total_pixels = width * height; unsigned char opcode; unsigned char flag = 0; int size = 0; int motion_x, motion_y; int x, y; unsigned char *opcode_buffer = s->buffer1; int opcode_buffer_size = s->buffer1_size; const unsigned char *imagedata_buffer = s->buffer2; /* pointers to segments inside the compressed chunk */ const unsigned char *huffman_segment; const unsigned char *size_segment; const unsigned char *vector_segment; const unsigned char *imagedata_segment; huffman_segment = s->buf + AV_RL16(&s->buf[0]); size_segment = s->buf + AV_RL16(&s->buf[2]); vector_segment = s->buf + AV_RL16(&s->buf[4]); imagedata_segment = s->buf + AV_RL16(&s->buf[6]); xan_huffman_decode(opcode_buffer, opcode_buffer_size, huffman_segment, s->size - (huffman_segment - s->buf) ); if (imagedata_segment[0] == 2) xan_unpack(s->buffer2, &imagedata_segment[1], s->buffer2_size); else imagedata_buffer = &imagedata_segment[1]; /* use the decoded data segments to build the frame */ x = y = 0; while (total_pixels) { opcode = *opcode_buffer++; size = 0; switch (opcode) { case 0: flag ^= 1; continue; case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 8: size = opcode; break; case 12: case 13: case 14: case 15: case 16: case 17: case 18: size += (opcode - 10); break; case 9: case 19: size = *size_segment++; break; case 10: case 20: size = AV_RB16(&size_segment[0]); size_segment += 2; break; case 11: case 21: size = AV_RB24(size_segment); size_segment += 3; break; } if (opcode < 12) { flag ^= 1; if (flag) { /* run of (size) pixels is unchanged from last frame */ xan_wc3_copy_pixel_run(s, x, y, size, 0, 0); } else { /* output a run of pixels from imagedata_buffer */ xan_wc3_output_pixel_run(s, imagedata_buffer, x, y, size); imagedata_buffer += size; } } else { /* run-based motion compensation from last frame */ motion_x = sign_extend(*vector_segment >> 4, 4); motion_y = sign_extend(*vector_segment & 0xF, 4); vector_segment++; /* copy a run of pixels from the previous frame */ xan_wc3_copy_pixel_run(s, x, y, size, motion_x, motion_y); flag = 0; } /* coordinate accounting */ total_pixels -= size; y += (x + size) / width; x = (x + size) % width; } }


static void qmp_input_start_alternate(Visitor *v, const char *name, GenericAlternate **obj, size_t size, bool promote_int, Error **errp) { QmpInputVisitor *qiv = to_qiv(v); QObject *qobj = qmp_input_get_object(qiv, name, false, errp); if (!qobj) { *obj = NULL; return; } *obj = g_malloc0(size); (*obj)->type = qobject_type(qobj); if (promote_int && (*obj)->type == QTYPE_QINT) { (*obj)->type = QTYPE_QFLOAT; } }


static void ac97_write(void *opaque, target_phys_addr_t addr, uint64_t value, unsigned size) { MilkymistAC97State *s = opaque; trace_milkymist_ac97_memory_write(addr, value); addr >>= 2; switch (addr) { case R_AC97_CTRL: /* always raise an IRQ according to the direction */ if (value & AC97_CTRL_RQEN) { if (value & AC97_CTRL_WRITE) { trace_milkymist_ac97_pulse_irq_crrequest(); qemu_irq_pulse(s->crrequest_irq); } else { trace_milkymist_ac97_pulse_irq_crreply(); qemu_irq_pulse(s->crreply_irq); } } /* RQEN is self clearing */ s->regs[addr] = value & ~AC97_CTRL_RQEN; break; case R_D_CTRL: case R_U_CTRL: s->regs[addr] = value; update_voices(s); break; case R_AC97_ADDR: case R_AC97_DATAOUT: case R_AC97_DATAIN: case R_D_ADDR: case R_D_REMAINING: case R_U_ADDR: case R_U_REMAINING: s->regs[addr] = value; break; default: error_report("milkymist_ac97: write access to unknown register 0x" TARGET_FMT_plx, addr); break; } }


static void mch_realize(PCIDevice *d, Error **errp) { int i; MCHPCIState *mch = MCH_PCI_DEVICE(d); /* setup pci memory mapping */ pc_pci_as_mapping_init(OBJECT(mch), mch->system_memory, mch->pci_address_space); /* if *disabled* show SMRAM to all CPUs */ memory_region_init_alias(&mch->smram_region, OBJECT(mch), "smram-region", mch->pci_address_space, 0xa0000, 0x20000); memory_region_add_subregion_overlap(mch->system_memory, 0xa0000, &mch->smram_region, 1); memory_region_set_enabled(&mch->smram_region, true); memory_region_init_alias(&mch->open_high_smram, OBJECT(mch), "smram-open-high", mch->ram_memory, 0xa0000, 0x20000); memory_region_add_subregion_overlap(mch->system_memory, 0xfeda0000, &mch->open_high_smram, 1); memory_region_set_enabled(&mch->open_high_smram, false); /* smram, as seen by SMM CPUs */ memory_region_init(&mch->smram, OBJECT(mch), "smram", 1ull << 32); memory_region_set_enabled(&mch->smram, true); memory_region_init_alias(&mch->low_smram, OBJECT(mch), "smram-low", mch->ram_memory, 0xa0000, 0x20000); memory_region_set_enabled(&mch->low_smram, true); memory_region_add_subregion(&mch->smram, 0xa0000, &mch->low_smram); memory_region_init_alias(&mch->high_smram, OBJECT(mch), "smram-high", mch->ram_memory, 0xa0000, 0x20000); memory_region_set_enabled(&mch->high_smram, true); memory_region_add_subregion(&mch->smram, 0xfeda0000, &mch->high_smram); memory_region_init_io(&mch->tseg_blackhole, OBJECT(mch), &tseg_blackhole_ops, NULL, "tseg-blackhole", 0); memory_region_set_enabled(&mch->tseg_blackhole, false); memory_region_add_subregion_overlap(mch->system_memory, mch->below_4g_mem_size, &mch->tseg_blackhole, 1); memory_region_init_alias(&mch->tseg_window, OBJECT(mch), "tseg-window", mch->ram_memory, mch->below_4g_mem_size, 0); memory_region_set_enabled(&mch->tseg_window, false); memory_region_add_subregion(&mch->smram, mch->below_4g_mem_size, &mch->tseg_window); object_property_add_const_link(qdev_get_machine(), "smram", OBJECT(&mch->smram), &error_abort); init_pam(DEVICE(mch), mch->ram_memory, mch->system_memory, mch->pci_address_space, &mch->pam_regions[0], PAM_BIOS_BASE, PAM_BIOS_SIZE); for (i = 0; i < 12; ++i) { init_pam(DEVICE(mch), mch->ram_memory, mch->system_memory, mch->pci_address_space, &mch->pam_regions[i+1], PAM_EXPAN_BASE + i * PAM_EXPAN_SIZE, PAM_EXPAN_SIZE); } /* Intel IOMMU (VT-d) */ if (machine_iommu(current_machine)) { mch_init_dmar(mch); } }


static void arm_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu) { DisasContext *dc = container_of(dcbase, DisasContext, base); CPUARMState *env = cpu->env_ptr; #ifdef CONFIG_USER_ONLY /* Intercept jump to the magic kernel page. */ if (dc->pc >= 0xffff0000) { /* We always get here via a jump, so know we are not in a conditional execution block. */ gen_exception_internal(EXCP_KERNEL_TRAP); dc->base.is_jmp = DISAS_NORETURN; return; } #endif if (dc->ss_active && !dc->pstate_ss) { /* Singlestep state is Active-pending. * If we're in this state at the start of a TB then either * a) we just took an exception to an EL which is being debugged * and this is the first insn in the exception handler * b) debug exceptions were masked and we just unmasked them * without changing EL (eg by clearing PSTATE.D) * In either case we're going to take a swstep exception in the * "did not step an insn" case, and so the syndrome ISV and EX * bits should be zero. */ assert(dc->base.num_insns == 1); gen_exception(EXCP_UDEF, syn_swstep(dc->ss_same_el, 0, 0), default_exception_el(dc)); dc->base.is_jmp = DISAS_NORETURN; return; } if (dc->thumb) { disas_thumb_insn(env, dc); if (dc->condexec_mask) { dc->condexec_cond = (dc->condexec_cond & 0xe) | ((dc->condexec_mask >> 4) & 1); dc->condexec_mask = (dc->condexec_mask << 1) & 0x1f; if (dc->condexec_mask == 0) { dc->condexec_cond = 0; } } } else { unsigned int insn = arm_ldl_code(env, dc->pc, dc->sctlr_b); dc->pc += 4; disas_arm_insn(dc, insn); } if (dc->condjmp && !dc->base.is_jmp) { gen_set_label(dc->condlabel); dc->condjmp = 0; } if (dc->base.is_jmp == DISAS_NEXT) { /* Translation stops when a conditional branch is encountered. * Otherwise the subsequent code could get translated several times. * Also stop translation when a page boundary is reached. This * ensures prefetch aborts occur at the right place. */ if (dc->pc >= dc->next_page_start || (dc->pc >= dc->next_page_start - 3 && insn_crosses_page(env, dc))) { /* We want to stop the TB if the next insn starts in a new page, * or if it spans between this page and the next. This means that * if we're looking at the last halfword in the page we need to * see if it's a 16-bit Thumb insn (which will fit in this TB) * or a 32-bit Thumb insn (which won't). * This is to avoid generating a silly TB with a single 16-bit insn * in it at the end of this page (which would execute correctly * but isn't very efficient). */ dc->base.is_jmp = DISAS_TOO_MANY; } } dc->base.pc_next = dc->pc; translator_loop_temp_check(&dc->base); }


void ppc_tlb_invalidate_one(CPUPPCState *env, target_ulong addr) { #if !defined(FLUSH_ALL_TLBS) PowerPCCPU *cpu = ppc_env_get_cpu(env); CPUState *cs; addr &= TARGET_PAGE_MASK; switch (env->mmu_model) { case POWERPC_MMU_SOFT_6xx: case POWERPC_MMU_SOFT_74xx: ppc6xx_tlb_invalidate_virt(env, addr, 0); if (env->id_tlbs == 1) { ppc6xx_tlb_invalidate_virt(env, addr, 1); } break; case POWERPC_MMU_SOFT_4xx: case POWERPC_MMU_SOFT_4xx_Z: ppc4xx_tlb_invalidate_virt(env, addr, env->spr[SPR_40x_PID]); break; case POWERPC_MMU_REAL: cpu_abort(CPU(cpu), "No TLB for PowerPC 4xx in real mode\n"); break; case POWERPC_MMU_MPC8xx: /* XXX: TODO */ cpu_abort(CPU(cpu), "MPC8xx MMU model is not implemented\n"); break; case POWERPC_MMU_BOOKE: /* XXX: TODO */ cpu_abort(CPU(cpu), "BookE MMU model is not implemented\n"); break; case POWERPC_MMU_BOOKE206: /* XXX: TODO */ cpu_abort(CPU(cpu), "BookE 2.06 MMU model is not implemented\n"); break; case POWERPC_MMU_32B: case POWERPC_MMU_601: /* tlbie invalidate TLBs for all segments */ addr &= ~((target_ulong)-1ULL << 28); cs = CPU(cpu); /* XXX: this case should be optimized, * giving a mask to tlb_flush_page */ tlb_flush_page(cs, addr | (0x0 << 28)); tlb_flush_page(cs, addr | (0x1 << 28)); tlb_flush_page(cs, addr | (0x2 << 28)); tlb_flush_page(cs, addr | (0x3 << 28)); tlb_flush_page(cs, addr | (0x4 << 28)); tlb_flush_page(cs, addr | (0x5 << 28)); tlb_flush_page(cs, addr | (0x6 << 28)); tlb_flush_page(cs, addr | (0x7 << 28)); tlb_flush_page(cs, addr | (0x8 << 28)); tlb_flush_page(cs, addr | (0x9 << 28)); tlb_flush_page(cs, addr | (0xA << 28)); tlb_flush_page(cs, addr | (0xB << 28)); tlb_flush_page(cs, addr | (0xC << 28)); tlb_flush_page(cs, addr | (0xD << 28)); tlb_flush_page(cs, addr | (0xE << 28)); tlb_flush_page(cs, addr | (0xF << 28)); break; #if defined(TARGET_PPC64) case POWERPC_MMU_64B: case POWERPC_MMU_2_03: case POWERPC_MMU_2_06: case POWERPC_MMU_2_06a: case POWERPC_MMU_2_07: case POWERPC_MMU_2_07a: /* tlbie invalidate TLBs for all segments */ /* XXX: given the fact that there are too many segments to invalidate, * and we still don't have a tlb_flush_mask(env, n, mask) in QEMU, * we just invalidate all TLBs */ tlb_flush(CPU(cpu), 1); break; #endif /* defined(TARGET_PPC64) */ default: /* XXX: TODO */ cpu_abort(CPU(cpu), "Unknown MMU model\n"); break; } #else ppc_tlb_invalidate_all(env); #endif }


static int scsi_qdev_init(DeviceState *qdev) { SCSIDevice *dev = SCSI_DEVICE(qdev); SCSIBus *bus = DO_UPCAST(SCSIBus, qbus, dev->qdev.parent_bus); SCSIDevice *d; int rc = -1; if (dev->channel > bus->info->max_channel) { error_report("bad scsi channel id: %d", dev->channel); goto err; } if (dev->id != -1 && dev->id > bus->info->max_target) { error_report("bad scsi device id: %d", dev->id); goto err; } if (dev->lun != -1 && dev->lun > bus->info->max_lun) { error_report("bad scsi device lun: %d", dev->lun); goto err; } if (dev->id == -1) { int id = -1; if (dev->lun == -1) { dev->lun = 0; } do { d = scsi_device_find(bus, dev->channel, ++id, dev->lun); } while (d && d->lun == dev->lun && id < bus->info->max_target); if (d && d->lun == dev->lun) { error_report("no free target"); goto err; } dev->id = id; } else if (dev->lun == -1) { int lun = -1; do { d = scsi_device_find(bus, dev->channel, dev->id, ++lun); } while (d && d->lun == lun && lun < bus->info->max_lun); if (d && d->lun == lun) { error_report("no free lun"); goto err; } dev->lun = lun; } else { d = scsi_device_find(bus, dev->channel, dev->id, dev->lun); assert(d); if (d->lun == dev->lun && dev != d) { error_report("lun already used by '%s'", d->qdev.id); goto err; } } QTAILQ_INIT(&dev->requests); rc = scsi_device_init(dev); if (rc == 0) { dev->vmsentry = qemu_add_vm_change_state_handler(scsi_dma_restart_cb, dev); } if (bus->info->hotplug) { bus->info->hotplug(bus, dev); } err: return rc; }


static BusState *qbus_find_recursive(BusState *bus, const char *name, const BusInfo *info) { DeviceState *dev; BusState *child, *ret; int match = 1; if (name && (strcmp(bus->name, name) != 0)) { match = 0; } if (info && (bus->info != info)) { match = 0; } if (match) { return bus; } LIST_FOREACH(dev, &bus->children, sibling) { LIST_FOREACH(child, &dev->child_bus, sibling) { ret = qbus_find_recursive(child, name, info); if (ret) { return ret; } } } return NULL; }


static void dump_metadata(void *ctx, AVDictionary *m, const char *indent) { if(m && !(m->count == 1 && av_dict_get(m, "language", NULL, 0))){ AVDictionaryEntry *tag=NULL; av_log(ctx, AV_LOG_INFO, "%sMetadata:\n", indent); while((tag=av_dict_get(m, "", tag, AV_DICT_IGNORE_SUFFIX))) { if(strcmp("language", tag->key)){ const char *p = tag->value; av_log(ctx, AV_LOG_INFO, "%s %-16s: ", indent, tag->key); while(*p) { char tmp[256]; size_t len = strcspn(p, "\xd\xa"); av_strlcpy(tmp, p, FFMIN(sizeof(tmp), len+1)); av_log(ctx, AV_LOG_INFO, "%s", tmp); p += len; if (*p == 0xd) av_log(ctx, AV_LOG_INFO, " "); if (*p == 0xa) av_log(ctx, AV_LOG_INFO, "\n%s %-16s: ", indent, ""); if (*p) p++; } av_log(ctx, AV_LOG_INFO, "\n"); } } } }


X86CPU *cpu_x86_create(const char *cpu_model, Error **errp) { X86CPU *cpu = NULL; ObjectClass *oc; CPUClass *cc; gchar **model_pieces; char *name, *features; Error *error = NULL; const char *typename; model_pieces = g_strsplit(cpu_model, ",", 2); if (!model_pieces[0]) { error_setg(&error, "Invalid/empty CPU model name"); goto out; } name = model_pieces[0]; features = model_pieces[1]; oc = x86_cpu_class_by_name(name); if (oc == NULL) { error_setg(&error, "Unable to find CPU definition: %s", name); goto out; } cc = CPU_CLASS(oc); typename = object_class_get_name(oc); cc->parse_features(typename, features, &error); cpu = X86_CPU(object_new(typename)); if (error) { goto out; } out: if (error != NULL) { error_propagate(errp, error); if (cpu) { object_unref(OBJECT(cpu)); cpu = NULL; } } g_strfreev(model_pieces); return cpu; }


static QEMUClock *qemu_new_clock(int type) { QEMUClock *clock; clock = g_malloc0(sizeof(QEMUClock)); clock->type = type; clock->enabled = true; clock->last = INT64_MIN; notifier_list_init(&clock->reset_notifiers); return clock; }


static gboolean gd_enter_event(GtkWidget *widget, GdkEventCrossing *crossing, gpointer opaque) { VirtualConsole *vc = opaque; GtkDisplayState *s = vc->s; if (!gd_is_grab_active(s) && gd_grab_on_hover(s)) { gd_grab_keyboard(vc); } return TRUE; }


sd_co_get_block_status(BlockDriverState *bs, int64_t sector_num, int nb_sectors, int *pnum) { BDRVSheepdogState *s = bs->opaque; SheepdogInode *inode = &s->inode; uint32_t object_size = (UINT32_C(1) << inode->block_size_shift); uint64_t offset = sector_num * BDRV_SECTOR_SIZE; unsigned long start = offset / object_size, end = DIV_ROUND_UP((sector_num + nb_sectors) * BDRV_SECTOR_SIZE, object_size); unsigned long idx; int64_t ret = BDRV_BLOCK_DATA | BDRV_BLOCK_OFFSET_VALID | offset; for (idx = start; idx < end; idx++) { if (inode->data_vdi_id[idx] == 0) { break; } } if (idx == start) { /* Get the longest length of unallocated sectors */ ret = 0; for (idx = start + 1; idx < end; idx++) { if (inode->data_vdi_id[idx] != 0) { break; } } } *pnum = (idx - start) * object_size / BDRV_SECTOR_SIZE; if (*pnum > nb_sectors) { *pnum = nb_sectors; } return ret; }


void laio_attach_aio_context(LinuxAioState *s, AioContext *new_context) { s->aio_context = new_context; s->completion_bh = aio_bh_new(new_context, qemu_laio_completion_bh, s); aio_set_event_notifier(new_context, &s->e, false, qemu_laio_completion_cb, NULL); }


process_tx_desc(E1000State *s, struct e1000_tx_desc *dp) { PCIDevice *d = PCI_DEVICE(s); uint32_t txd_lower = le32_to_cpu(dp->lower.data); uint32_t dtype = txd_lower & (E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D); unsigned int split_size = txd_lower & 0xffff, bytes, sz; unsigned int msh = 0xfffff; uint64_t addr; struct e1000_context_desc *xp = (struct e1000_context_desc *)dp; struct e1000_tx *tp = &s->tx; s->mit_ide |= (txd_lower & E1000_TXD_CMD_IDE); if (dtype == E1000_TXD_CMD_DEXT) { /* context descriptor */ e1000x_read_tx_ctx_descr(xp, &tp->props); tp->tso_frames = 0; if (tp->props.tucso == 0) { /* this is probably wrong */ DBGOUT(TXSUM, "TCP/UDP: cso 0!\n"); tp->props.tucso = tp->props.tucss + (tp->props.tcp ? 16 : 6); } return; } else if (dtype == (E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D)) { // data descriptor if (tp->size == 0) { tp->props.sum_needed = le32_to_cpu(dp->upper.data) >> 8; } tp->props.cptse = (txd_lower & E1000_TXD_CMD_TSE) ? 1 : 0; } else { // legacy descriptor tp->props.cptse = 0; } if (e1000x_vlan_enabled(s->mac_reg) && e1000x_is_vlan_txd(txd_lower) && (tp->props.cptse || txd_lower & E1000_TXD_CMD_EOP)) { tp->vlan_needed = 1; stw_be_p(tp->vlan_header, le16_to_cpu(s->mac_reg[VET])); stw_be_p(tp->vlan_header + 2, le16_to_cpu(dp->upper.fields.special)); } addr = le64_to_cpu(dp->buffer_addr); if (tp->props.tse && tp->props.cptse) { msh = tp->props.hdr_len + tp->props.mss; do { bytes = split_size; if (tp->size + bytes > msh) bytes = msh - tp->size; bytes = MIN(sizeof(tp->data) - tp->size, bytes); pci_dma_read(d, addr, tp->data + tp->size, bytes); sz = tp->size + bytes; if (sz >= tp->props.hdr_len && tp->size < tp->props.hdr_len) { memmove(tp->header, tp->data, tp->props.hdr_len); } tp->size = sz; addr += bytes; if (sz == msh) { xmit_seg(s); memmove(tp->data, tp->header, tp->props.hdr_len); tp->size = tp->props.hdr_len; } split_size -= bytes; } while (bytes && split_size); } else if (!tp->props.tse && tp->props.cptse) { // context descriptor TSE is not set, while data descriptor TSE is set DBGOUT(TXERR, "TCP segmentation error\n"); } else { split_size = MIN(sizeof(tp->data) - tp->size, split_size); pci_dma_read(d, addr, tp->data + tp->size, split_size); tp->size += split_size; } if (!(txd_lower & E1000_TXD_CMD_EOP)) return; if (!(tp->props.tse && tp->props.cptse && tp->size < tp->props.hdr_len)) { xmit_seg(s); } tp->tso_frames = 0; tp->props.sum_needed = 0; tp->vlan_needed = 0; tp->size = 0; tp->props.cptse = 0; }


int unix_socket_outgoing(const char *path) { Error *local_err = NULL; int fd = unix_connect(path, &local_err); if (local_err != NULL) { qerror_report_err(local_err); error_free(local_err); } return fd; }


static ssize_t nbd_receive_request(int csock, struct nbd_request *request) { uint8_t buf[4 + 4 + 8 + 8 + 4]; uint32_t magic; if (read_sync(csock, buf, sizeof(buf)) != sizeof(buf)) { LOG("read failed"); errno = EINVAL; return -1; } /* Request [ 0 .. 3] magic (NBD_REQUEST_MAGIC) [ 4 .. 7] type (0 == READ, 1 == WRITE) [ 8 .. 15] handle [16 .. 23] from [24 .. 27] len */ magic = be32_to_cpup((uint32_t*)buf); request->type = be32_to_cpup((uint32_t*)(buf + 4)); request->handle = be64_to_cpup((uint64_t*)(buf + 8)); request->from = be64_to_cpup((uint64_t*)(buf + 16)); request->len = be32_to_cpup((uint32_t*)(buf + 24)); TRACE("Got request: " "{ magic = 0x%x, .type = %d, from = %" PRIu64" , len = %u }", magic, request->type, request->from, request->len); if (magic != NBD_REQUEST_MAGIC) { LOG("invalid magic (got 0x%x)", magic); errno = EINVAL; return -1; } return 0; }


static void raw_close_fd_pool(BDRVRawState *s) { int i; for (i = 0; i < RAW_FD_POOL_SIZE; i++) { if (s->fd_pool[i] != -1) { close(s->fd_pool[i]); s->fd_pool[i] = -1; } } }


static UHCIAsync *uhci_async_alloc(UHCIState *s) { UHCIAsync *async = g_malloc(sizeof(UHCIAsync)); memset(&async->packet, 0, sizeof(async->packet)); async->uhci = s; async->valid = 0; async->td = 0; async->token = 0; async->done = 0; async->isoc = 0; usb_packet_init(&async->packet); qemu_sglist_init(&async->sgl, 1); return async; }


static void apic_startup(APICState *s, int vector_num) { CPUState *env = s->cpu_env; if (!env->halted) return; env->eip = 0; cpu_x86_load_seg_cache(env, R_CS, vector_num << 8, vector_num << 12, 0xffff, 0); env->halted = 0; }


void kvm_s390_virtio_irq(S390CPU *cpu, int config_change, uint64_t token) { kvm_s390_interrupt_internal(cpu, KVM_S390_INT_VIRTIO, config_change, token, 1); }


static void bdrv_io_limits_intercept(BlockDriverState *bs, unsigned int bytes, bool is_write) { /* does this io must wait */ bool must_wait = throttle_schedule_timer(&bs->throttle_state, is_write); /* if must wait or any request of this type throttled queue the IO */ if (must_wait || !qemu_co_queue_empty(&bs->throttled_reqs[is_write])) { qemu_co_queue_wait(&bs->throttled_reqs[is_write]); } /* the IO will be executed, do the accounting */ throttle_account(&bs->throttle_state, is_write, bytes); /* if the next request must wait -> do nothing */ if (throttle_schedule_timer(&bs->throttle_state, is_write)) { return; } /* else queue next request for execution */ qemu_co_queue_next(&bs->throttled_reqs[is_write]); }


static int parse_bintree(Indeo3DecodeContext *ctx, AVCodecContext *avctx, Plane *plane, int code, Cell *ref_cell, const int depth, const int strip_width) { Cell curr_cell; int bytes_used; if (depth <= 0) { av_log(avctx, AV_LOG_ERROR, "Stack overflow (corrupted binary tree)!\n"); return AVERROR_INVALIDDATA; // unwind recursion } curr_cell = *ref_cell; // clone parent cell if (code == H_SPLIT) { SPLIT_CELL(ref_cell->height, curr_cell.height); ref_cell->ypos += curr_cell.height; ref_cell->height -= curr_cell.height; } else if (code == V_SPLIT) { if (curr_cell.width > strip_width) { /* split strip */ curr_cell.width = (curr_cell.width <= (strip_width << 1) ? 1 : 2) * strip_width; } else SPLIT_CELL(ref_cell->width, curr_cell.width); ref_cell->xpos += curr_cell.width; ref_cell->width -= curr_cell.width; } while (1) { /* loop until return */ RESYNC_BITSTREAM; switch (code = get_bits(&ctx->gb, 2)) { case H_SPLIT: case V_SPLIT: if (parse_bintree(ctx, avctx, plane, code, &curr_cell, depth - 1, strip_width)) return AVERROR_INVALIDDATA; break; case INTRA_NULL: if (!curr_cell.tree) { /* MC tree INTRA code */ curr_cell.mv_ptr = 0; /* mark the current strip as INTRA */ curr_cell.tree = 1; /* enter the VQ tree */ } else { /* VQ tree NULL code */ RESYNC_BITSTREAM; code = get_bits(&ctx->gb, 2); if (code >= 2) { av_log(avctx, AV_LOG_ERROR, "Invalid VQ_NULL code: %d\n", code); return AVERROR_INVALIDDATA; } if (code == 1) av_log(avctx, AV_LOG_ERROR, "SkipCell procedure not implemented yet!\n"); CHECK_CELL copy_cell(ctx, plane, &curr_cell); return 0; } break; case INTER_DATA: if (!curr_cell.tree) { /* MC tree INTER code */ /* get motion vector index and setup the pointer to the mv set */ if (!ctx->need_resync) ctx->next_cell_data = &ctx->gb.buffer[(get_bits_count(&ctx->gb) + 7) >> 3]; curr_cell.mv_ptr = &ctx->mc_vectors[*(ctx->next_cell_data++) << 1]; curr_cell.tree = 1; /* enter the VQ tree */ UPDATE_BITPOS(8); } else { /* VQ tree DATA code */ if (!ctx->need_resync) ctx->next_cell_data = &ctx->gb.buffer[(get_bits_count(&ctx->gb) + 7) >> 3]; CHECK_CELL bytes_used = decode_cell(ctx, avctx, plane, &curr_cell, ctx->next_cell_data, ctx->last_byte); if (bytes_used < 0) return AVERROR_INVALIDDATA; UPDATE_BITPOS(bytes_used << 3); ctx->next_cell_data += bytes_used; return 0; } break; } }//while return 0; }


int64_t swr_next_pts(struct SwrContext *s, int64_t pts){ if(pts == INT64_MIN) return s->outpts; if(s->min_compensation >= FLT_MAX) { return (s->outpts = pts - swr_get_delay(s, s->in_sample_rate * (int64_t)s->out_sample_rate)); } else { int64_t delta = pts - swr_get_delay(s, s->in_sample_rate * (int64_t)s->out_sample_rate) - s->outpts; double fdelta = delta /(double)(s->in_sample_rate * (int64_t)s->out_sample_rate); if(fabs(fdelta) > s->min_compensation) { if(!s->outpts || fabs(fdelta) > s->min_hard_compensation){ int ret; if(delta > 0) ret = swr_inject_silence(s, delta / s->out_sample_rate); else ret = swr_drop_output (s, -delta / s-> in_sample_rate); if(ret<0){ av_log(s, AV_LOG_ERROR, "Failed to compensate for timestamp delta of %f\n", fdelta); } } else if(s->soft_compensation_duration && s->max_soft_compensation) { int duration = s->out_sample_rate * s->soft_compensation_duration; double max_soft_compensation = s->max_soft_compensation / (s->max_soft_compensation < 0 ? -s->in_sample_rate : 1); int comp = av_clipf(fdelta, -max_soft_compensation, max_soft_compensation) * duration ; av_log(s, AV_LOG_VERBOSE, "compensating audio timestamp drift:%f compensation:%d in:%d\n", fdelta, comp, duration); swr_set_compensation(s, comp, duration); } } return s->outpts; } }


int av_utf8_decode(int32_t *codep, const uint8_t **bufp, const uint8_t *buf_end, unsigned int flags) { const uint8_t *p = *bufp; uint32_t top; uint64_t code; int ret = 0; if (p >= buf_end) return 0; code = *p++; /* first sequence byte starts with 10, or is 1111-1110 or 1111-1111, which is not admitted */ if ((code & 0xc0) == 0x80 || code >= 0xFE) { ret = AVERROR(EILSEQ); goto end; } top = (code & 128) >> 1; while (code & top) { int tmp; if (p >= buf_end) { (*bufp) ++; return AVERROR(EILSEQ); /* incomplete sequence */ } /* we assume the byte to be in the form 10xx-xxxx */ tmp = *p++ - 128; /* strip leading 1 */ if (tmp>>6) { (*bufp) ++; return AVERROR(EILSEQ); } code = (code<<6) + tmp; top <<= 5; } code &= (top << 1) - 1; if (code >= 1<<31) { ret = AVERROR(EILSEQ); /* out-of-range value */ goto end; } *codep = code; if (code > 0x10FFFF && !(flags & AV_UTF8_FLAG_ACCEPT_INVALID_BIG_CODES)) ret = AVERROR(EILSEQ); if (code < 0x20 && code != 0x9 && code != 0xA && code != 0xD && flags & AV_UTF8_FLAG_EXCLUDE_XML_INVALID_CONTROL_CODES) ret = AVERROR(EILSEQ); if (code >= 0xD800 && code <= 0xDFFF && !(flags & AV_UTF8_FLAG_ACCEPT_SURROGATES)) ret = AVERROR(EILSEQ); if ((code == 0xFFFE || code == 0xFFFF) && !(flags & AV_UTF8_FLAG_ACCEPT_NON_CHARACTERS)) ret = AVERROR(EILSEQ); end: *bufp = p; return ret; }


static av_always_inline av_flatten void h264_loop_filter_luma_intra_c(uint8_t *pix, int xstride, int ystride, int alpha, int beta) { int d; for( d = 0; d < 16; d++ ) { const int p2 = pix[-3*xstride]; const int p1 = pix[-2*xstride]; const int p0 = pix[-1*xstride]; const int q0 = pix[ 0*xstride]; const int q1 = pix[ 1*xstride]; const int q2 = pix[ 2*xstride]; if( FFABS( p0 - q0 ) < alpha && FFABS( p1 - p0 ) < beta && FFABS( q1 - q0 ) < beta ) { if(FFABS( p0 - q0 ) < (( alpha >> 2 ) + 2 )){ if( FFABS( p2 - p0 ) < beta) { const int p3 = pix[-4*xstride]; /* p0', p1', p2' */ pix[-1*xstride] = ( p2 + 2*p1 + 2*p0 + 2*q0 + q1 + 4 ) >> 3; pix[-2*xstride] = ( p2 + p1 + p0 + q0 + 2 ) >> 2; pix[-3*xstride] = ( 2*p3 + 3*p2 + p1 + p0 + q0 + 4 ) >> 3; } else { /* p0' */ pix[-1*xstride] = ( 2*p1 + p0 + q1 + 2 ) >> 2; } if( FFABS( q2 - q0 ) < beta) { const int q3 = pix[3*xstride]; /* q0', q1', q2' */ pix[0*xstride] = ( p1 + 2*p0 + 2*q0 + 2*q1 + q2 + 4 ) >> 3; pix[1*xstride] = ( p0 + q0 + q1 + q2 + 2 ) >> 2; pix[2*xstride] = ( 2*q3 + 3*q2 + q1 + q0 + p0 + 4 ) >> 3; } else { /* q0' */ pix[0*xstride] = ( 2*q1 + q0 + p1 + 2 ) >> 2; } }else{ /* p0', q0' */ pix[-1*xstride] = ( 2*p1 + p0 + q1 + 2 ) >> 2; pix[ 0*xstride] = ( 2*q1 + q0 + p1 + 2 ) >> 2; } } pix += ystride; } }


static void sigbus_handler(int signal) { siglongjmp(sigjump, 1); }


void fw_cfg_add_bytes(FWCfgState *s, uint16_t key, uint8_t *data, uint32_t len) { int arch = !!(key & FW_CFG_ARCH_LOCAL); key &= FW_CFG_ENTRY_MASK; assert(key < FW_CFG_MAX_ENTRY); s->entries[arch][key].data = data; s->entries[arch][key].len = len; }


static void set_bmc_global_enables(IPMIBmcSim *ibs, uint8_t *cmd, unsigned int cmd_len, uint8_t *rsp, unsigned int *rsp_len, unsigned int max_rsp_len) { IPMI_CHECK_CMD_LEN(3); set_global_enables(ibs, cmd[2]); }