*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA
*/
#include <stdarg.h>
#include <stdlib.h>
tcg_gen_shri_tl(ret, arg1, -arg2);
}
-/* XXX: add faster immediate case */
static void gen_rot_rm_T1(DisasContext *s, int ot, int op1,
int is_right)
{
tcg_temp_free(a0);
}
+static void gen_rot_rm_im(DisasContext *s, int ot, int op1, int op2,
+ int is_right)
+{
+ int mask;
+ int data_bits;
+ TCGv t0, t1, a0;
+
+ /* XXX: inefficient, but we must use local temps */
+ t0 = tcg_temp_local_new();
+ t1 = tcg_temp_local_new();
+ a0 = tcg_temp_local_new();
+
+ if (ot == OT_QUAD)
+ mask = 0x3f;
+ else
+ mask = 0x1f;
+
+ /* load */
+ if (op1 == OR_TMP0) {
+ tcg_gen_mov_tl(a0, cpu_A0);
+ gen_op_ld_v(ot + s->mem_index, t0, a0);
+ } else {
+ gen_op_mov_v_reg(ot, t0, op1);
+ }
+
+ gen_extu(ot, t0);
+ tcg_gen_mov_tl(t1, t0);
+
+ op2 &= mask;
+ data_bits = 8 << ot;
+ if (op2 != 0) {
+ int shift = op2 & ((1 << (3 + ot)) - 1);
+ if (is_right) {
+ tcg_gen_shri_tl(cpu_tmp4, t0, shift);
+ tcg_gen_shli_tl(t0, t0, data_bits - shift);
+ }
+ else {
+ tcg_gen_shli_tl(cpu_tmp4, t0, shift);
+ tcg_gen_shri_tl(t0, t0, data_bits - shift);
+ }
+ tcg_gen_or_tl(t0, t0, cpu_tmp4);
+ }
+
+ /* store */
+ if (op1 == OR_TMP0) {
+ gen_op_st_v(ot + s->mem_index, t0, a0);
+ } else {
+ gen_op_mov_reg_v(ot, op1, t0);
+ }
+
+ if (op2 != 0) {
+ /* update eflags */
+ if (s->cc_op != CC_OP_DYNAMIC)
+ gen_op_set_cc_op(s->cc_op);
+
+ gen_compute_eflags(cpu_cc_src);
+ tcg_gen_andi_tl(cpu_cc_src, cpu_cc_src, ~(CC_O | CC_C));
+ tcg_gen_xor_tl(cpu_tmp0, t1, t0);
+ tcg_gen_lshift(cpu_tmp0, cpu_tmp0, 11 - (data_bits - 1));
+ tcg_gen_andi_tl(cpu_tmp0, cpu_tmp0, CC_O);
+ tcg_gen_or_tl(cpu_cc_src, cpu_cc_src, cpu_tmp0);
+ if (is_right) {
+ tcg_gen_shri_tl(t0, t0, data_bits - 1);
+ }
+ tcg_gen_andi_tl(t0, t0, CC_C);
+ tcg_gen_or_tl(cpu_cc_src, cpu_cc_src, t0);
+
+ tcg_gen_discard_tl(cpu_cc_dst);
+ tcg_gen_movi_i32(cpu_cc_op, CC_OP_EFLAGS);
+ s->cc_op = CC_OP_EFLAGS;
+ }
+
+ tcg_temp_free(t0);
+ tcg_temp_free(t1);
+ tcg_temp_free(a0);
+}
+
/* XXX: add faster immediate = 1 case */
static void gen_rotc_rm_T1(DisasContext *s, int ot, int op1,
int is_right)
static void gen_shifti(DisasContext *s1, int op, int ot, int d, int c)
{
switch(op) {
+ case OP_ROL:
+ gen_rot_rm_im(s1, ot, d, c, 0);
+ break;
+ case OP_ROR:
+ gen_rot_rm_im(s1, ot, d, c, 1);
+ break;
case OP_SHL:
case OP_SHL1:
gen_shift_rm_im(s1, ot, d, c, 0, 0);
target_ulong next_eip, tval;
int rex_w, rex_r;
- if (unlikely(loglevel & CPU_LOG_TB_OP))
+ if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP)))
tcg_gen_debug_insn_start(pc_start);
s->pc = pc_start;
prefixes = 0;
tval += s->pc - s->cs_base;
if (s->dflag == 0)
tval &= 0xffff;
+ else if(!CODE64(s))
+ tval &= 0xffffffff;
gen_jmp(s, tval);
break;
case 0xea: /* ljmp im */
gen_jmp_im(pc_start - s->cs_base);
gen_helper_into(tcg_const_i32(s->pc - pc_start));
break;
+#ifdef WANT_ICEBP
case 0xf1: /* icebp (undocumented, exits to external debugger) */
gen_svm_check_intercept(s, pc_start, SVM_EXIT_ICEBP);
#if 1
cpu_set_log(CPU_LOG_INT | CPU_LOG_TB_IN_ASM);
#endif
break;
+#endif
case 0xfa: /* cli */
if (!s->vm86) {
if (s->cpl <= s->iopl) {
#ifdef TARGET_X86_64
if (dflag == 2) {
gen_op_mov_TN_reg(OT_QUAD, 0, reg);
- tcg_gen_bswap_i64(cpu_T[0], cpu_T[0]);
+ tcg_gen_bswap64_i64(cpu_T[0], cpu_T[0]);
gen_op_mov_reg_T0(OT_QUAD, reg);
} else
- {
- TCGv_i32 tmp0;
- gen_op_mov_TN_reg(OT_LONG, 0, reg);
-
- tmp0 = tcg_temp_new_i32();
- tcg_gen_trunc_i64_i32(tmp0, cpu_T[0]);
- tcg_gen_bswap_i32(tmp0, tmp0);
- tcg_gen_extu_i32_i64(cpu_T[0], tmp0);
- gen_op_mov_reg_T0(OT_LONG, reg);
- }
-#else
+#endif
{
gen_op_mov_TN_reg(OT_LONG, 0, reg);
- tcg_gen_bswap_i32(cpu_T[0], cpu_T[0]);
+ tcg_gen_ext32u_tl(cpu_T[0], cpu_T[0]);
+ tcg_gen_bswap32_tl(cpu_T[0], cpu_T[0]);
gen_op_mov_reg_T0(OT_LONG, reg);
}
-#endif
break;
case 0xd6: /* salc */
if (CODE64(s))
break;
case 4: /* smsw */
gen_svm_check_intercept(s, pc_start, SVM_EXIT_READ_CR0);
+#if defined TARGET_X86_64 && defined WORDS_BIGENDIAN
+ tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,cr[0]) + 4);
+#else
tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,cr[0]));
+#endif
gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 1);
break;
case 6: /* lmsw */
gen_icount_start();
for(;;) {
- if (unlikely(env->breakpoints)) {
- for (bp = env->breakpoints; bp != NULL; bp = bp->next) {
+ if (unlikely(!TAILQ_EMPTY(&env->breakpoints))) {
+ TAILQ_FOREACH(bp, &env->breakpoints, entry) {
if (bp->pc == pc_ptr) {
gen_debug(dc, pc_ptr - dc->cs_base);
break;
gen_eob(dc);
break;
}
+ if (singlestep) {
+ gen_jmp_im(pc_ptr - dc->cs_base);
+ gen_eob(dc);
+ break;
+ }
}
if (tb->cflags & CF_LAST_IO)
gen_io_end();
}
#ifdef DEBUG_DISAS
- if (loglevel & CPU_LOG_TB_CPU) {
- cpu_dump_state(env, logfile, fprintf, X86_DUMP_CCOP);
- }
- if (loglevel & CPU_LOG_TB_IN_ASM) {
+ log_cpu_state_mask(CPU_LOG_TB_CPU, env, X86_DUMP_CCOP);
+ if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
int disas_flags;
- fprintf(logfile, "----------------\n");
- fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
+ qemu_log("----------------\n");
+ qemu_log("IN: %s\n", lookup_symbol(pc_start));
#ifdef TARGET_X86_64
if (dc->code64)
disas_flags = 2;
else
#endif
disas_flags = !dc->code32;
- target_disas(logfile, pc_start, pc_ptr - pc_start, disas_flags);
- fprintf(logfile, "\n");
+ log_target_disas(pc_start, pc_ptr - pc_start, disas_flags);
+ qemu_log("\n");
}
#endif
{
int cc_op;
#ifdef DEBUG_DISAS
- if (loglevel & CPU_LOG_TB_OP) {
+ if (qemu_loglevel_mask(CPU_LOG_TB_OP)) {
int i;
- fprintf(logfile, "RESTORE:\n");
+ qemu_log("RESTORE:\n");
for(i = 0;i <= pc_pos; i++) {
if (gen_opc_instr_start[i]) {
- fprintf(logfile, "0x%04x: " TARGET_FMT_lx "\n", i, gen_opc_pc[i]);
+ qemu_log("0x%04x: " TARGET_FMT_lx "\n", i, gen_opc_pc[i]);
}
}
- fprintf(logfile, "spc=0x%08lx pc_pos=0x%x eip=" TARGET_FMT_lx " cs_base=%x\n",
+ qemu_log("spc=0x%08lx pc_pos=0x%x eip=" TARGET_FMT_lx " cs_base=%x\n",
searched_pc, pc_pos, gen_opc_pc[pc_pos] - tb->cs_base,
(uint32_t)tb->cs_base);
}