From patchwork Wed Aug 17 20:46:25 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bryce Lanham X-Patchwork-Id: 110384 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [140.186.70.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 762D4B6F8A for ; Thu, 18 Aug 2011 08:06:35 +1000 (EST) Received: from localhost ([::1]:51777 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Qtn4F-0000Nc-CR for incoming@patchwork.ozlabs.org; Wed, 17 Aug 2011 16:50:27 -0400 Received: from eggs.gnu.org ([140.186.70.92]:46995) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Qtn2g-00065i-OQ for qemu-devel@nongnu.org; Wed, 17 Aug 2011 16:48:52 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Qtn2e-0006i2-Fz for qemu-devel@nongnu.org; Wed, 17 Aug 2011 16:48:50 -0400 Received: from mail-gx0-f173.google.com ([209.85.161.173]:54221) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Qtn2e-0006aR-Cz for qemu-devel@nongnu.org; Wed, 17 Aug 2011 16:48:48 -0400 Received: by mail-gx0-f173.google.com with SMTP id 26so1230323gxk.4 for ; Wed, 17 Aug 2011 13:48:48 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=from:to:cc:subject:date:message-id:x-mailer:in-reply-to:references; bh=Y/O36iShJtK93ZWPkMXPAIYcW5mM1qQchj9OMI+Aoww=; b=ldCl/9QOEp1PtKvIFqJTY62y2RgKoJAh0P1lGtHj30+0Dpeahzr8Tz7P3KRNAvGaG+ bkr54BiT0x1CS6HV/+8TWgmmfRQR37n3h3CebBpzhktKO+vuHyhynHD3jP6zwv/qO6o6 lm6NXiXiwK7yYjYhwBmfZTcmA0vdCy/1jhVco= Received: by 10.236.22.129 with SMTP id t1mr2326363yht.184.1313614128017; Wed, 17 Aug 2011 13:48:48 -0700 (PDT) Received: from localhost.localdomain (betelgeuse.cs.uchicago.edu [128.135.24.226]) by mx.google.com with ESMTPS id a29sm1237029yhj.59.2011.08.17.13.48.46 (version=TLSv1/SSLv3 cipher=OTHER); Wed, 17 Aug 2011 13:48:46 -0700 (PDT) From: Bryce Lanham To: qemu-devel@nongnu.org Date: Wed, 17 Aug 2011 15:46:25 -0500 Message-Id: <1313614076-28878-21-git-send-email-blanham@gmail.com> X-Mailer: git-send-email 1.7.2.3 In-Reply-To: <1313614076-28878-1-git-send-email-blanham@gmail.com> References: <1313614076-28878-1-git-send-email-blanham@gmail.com> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6 (newer, 2) X-Received-From: 209.85.161.173 Cc: Andreas Schwab , Laurent Vivier Subject: [Qemu-devel] [PATCH 020/111] m68k: add "byte", "word" and memory shift X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org From: Laurent Vivier This patch defines shift8_im, shift16_im, shift8_reg, shift16_reg, shift_mem and attach them to M68000 feature. Signed-off-by: Andreas Schwab Signed-off-by: Laurent Vivier --- target-m68k/cpu.h | 2 + target-m68k/helper.c | 160 +++++++++++++++++++++++++++-------------------- target-m68k/helpers.h | 12 +++- target-m68k/translate.c | 155 +++++++++++++++++++++++++++++++++++++++++++--- 4 files changed, 249 insertions(+), 80 deletions(-) diff --git a/target-m68k/cpu.h b/target-m68k/cpu.h index ff57564..91d3141 100644 --- a/target-m68k/cpu.h +++ b/target-m68k/cpu.h @@ -147,6 +147,8 @@ enum { CC_OP_SUBXB, /* CC_DEST = result, CC_SRC = source */ CC_OP_SUBXW, /* CC_DEST = result, CC_SRC = source */ CC_OP_SUBX, /* CC_DEST = result, CC_SRC = source */ + CC_OP_SHIFTB, /* CC_DEST = result, CC_SRC = carry */ + CC_OP_SHIFTW, /* CC_DEST = result, CC_SRC = carry */ CC_OP_SHIFT, /* CC_DEST = result, CC_SRC = carry */ }; diff --git a/target-m68k/helper.c b/target-m68k/helper.c index dd9079f..0025ab5 100644 --- a/target-m68k/helper.c +++ b/target-m68k/helper.c @@ -287,6 +287,12 @@ void cpu_m68k_flush_flags(CPUM68KState *env, int cc_op) flags |= CCF_V; \ } while (0) +#define SET_FLAGS_SHIFT(type) do { \ + SET_NZ((type)dest); \ + if (src) \ + flags |= CCF_C; \ + } while(0) + flags = 0; src = env->cc_src; dest = env->cc_dest; @@ -333,10 +339,14 @@ void cpu_m68k_flush_flags(CPUM68KState *env, int cc_op) case CC_OP_SUBX: SET_FLAGS_SUBX(int32_t, uint32_t); break; + case CC_OP_SHIFTB: + SET_FLAGS_SHIFT(int8_t); + break; + case CC_OP_SHIFTW: + SET_FLAGS_SHIFT(int16_t); + break; case CC_OP_SHIFT: - SET_NZ(dest); - if (src) - flags |= CCF_C; + SET_FLAGS_SHIFT(int32_t); break; default: cpu_abort(env, "Bad CC_OP %d", cc_op); @@ -538,77 +548,89 @@ void HELPER(set_sr)(CPUState *env, uint32_t val) m68k_switch_sp(env); } -uint32_t HELPER(shl_cc)(CPUState *env, uint32_t val, uint32_t shift) -{ - uint32_t result; - uint32_t cf; - - shift &= 63; - if (shift == 0) { - result = val; - cf = env->cc_src & CCF_C; - } else if (shift < 32) { - result = val << shift; - cf = (val >> (32 - shift)) & 1; - } else if (shift == 32) { - result = 0; - cf = val & 1; - } else /* shift > 32 */ { - result = 0; - cf = 0; - } - env->cc_src = cf; - env->cc_x = (cf != 0); - env->cc_dest = result; - return result; -} - -uint32_t HELPER(shr_cc)(CPUState *env, uint32_t val, uint32_t shift) -{ - uint32_t result; - uint32_t cf; - - shift &= 63; - if (shift == 0) { - result = val; - cf = env->cc_src & CCF_C; - } else if (shift < 32) { - result = val >> shift; - cf = (val >> (shift - 1)) & 1; - } else if (shift == 32) { - result = 0; - cf = val >> 31; - } else /* shift > 32 */ { - result = 0; - cf = 0; - } - env->cc_src = cf; - env->cc_x = (cf != 0); - env->cc_dest = result; - return result; -} - -uint32_t HELPER(sar_cc)(CPUState *env, uint32_t val, uint32_t shift) -{ - uint32_t result; - uint32_t cf; - - shift &= 63; - if (shift == 0) { - result = val; - cf = (env->cc_src & CCF_C) != 0; - } else if (shift < 32) { - result = (int32_t)val >> shift; - cf = (val >> (shift - 1)) & 1; - } else /* shift >= 32 */ { - result = (int32_t)val >> 31; - cf = val >> 31; - } - env->cc_src = cf; - env->cc_x = cf; - env->cc_dest = result; - return result; -} +#define HELPER_SHL(type, bits) \ +uint32_t HELPER(glue(glue(shl, bits),_cc))(CPUState *env, uint32_t val, uint32_t shift) \ +{ \ + type result; \ + uint32_t cf; \ + shift &= 63; \ + if (shift == 0) { \ + result = (type)val; \ + cf = env->cc_src & CCF_C; \ + } else if (shift < bits) { \ + result = (type)val << shift; \ + cf = ((type)val >> (bits - shift)) & 1; \ + } else if (shift == bits) { \ + result = 0; \ + cf = val & 1; \ + } else /* shift > bits */ { \ + result = 0; \ + cf = 0; \ + } \ + env->cc_src = cf; \ + env->cc_x = (cf != 0); \ + env->cc_dest = result; \ + return result; \ +} + +HELPER_SHL(uint8_t, 8) +HELPER_SHL(uint16_t, 16) +HELPER_SHL(uint32_t, 32) + +#define HELPER_SHR(type, bits) \ +uint32_t HELPER(glue(glue(shr, bits), _cc))(CPUState *env, uint32_t val, uint32_t shift) \ +{ \ + type result; \ + uint32_t cf; \ + shift &= 63; \ + if (shift == 0) { \ + result = (type)val; \ + cf = env->cc_src & CCF_C; \ + } else if (shift < bits) { \ + result = (type)val >> shift; \ + cf = ((type)val >> (shift - 1)) & 1; \ + } else if (shift == bits) { \ + result = 0; \ + cf = (type)val >> (bits - 1); \ + } else /* shift > bits */ { \ + result = 0; \ + cf = 0; \ + } \ + env->cc_src = cf; \ + env->cc_x = (cf != 0); \ + env->cc_dest = result; \ + return result; \ +} + +HELPER_SHR(uint8_t, 8) +HELPER_SHR(uint16_t, 16) +HELPER_SHR(uint32_t, 32) + +#define HELPER_SAR(type, bits) \ +uint32_t HELPER(glue(glue(sar, bits), _cc))(CPUState *env, uint32_t val, uint32_t shift) \ +{ \ + type result; \ + uint32_t cf; \ + shift &= 63; \ + if (shift == 0) { \ + result = (type)val; \ + cf = (env->cc_src & CCF_C) != 0; \ + } else if (shift < bits) { \ + result = (type)val >> shift; \ + cf = ((type)val >> (shift - 1)) & 1; \ + } else /* shift >= bits */ { \ + result = (type)val >> (bits - 1); \ + cf = (type)val >> (bits - 1); \ + } \ + env->cc_src = cf; \ + env->cc_x = cf; \ + env->cc_dest = result; \ + return result; \ +} + +HELPER_SAR(int8_t, 8) +HELPER_SAR(int16_t, 16) +HELPER_SAR(int32_t, 32) /* FPU helpers. */ uint32_t HELPER(f64_to_i32)(CPUState *env, float64 val) diff --git a/target-m68k/helpers.h b/target-m68k/helpers.h index ca2bf82..d1993ab 100644 --- a/target-m68k/helpers.h +++ b/target-m68k/helpers.h @@ -13,9 +13,15 @@ DEF_HELPER_3(mulu64, i32, env, i32, i32) DEF_HELPER_3(muls64, i32, env, i32, i32) DEF_HELPER_3(addx_cc, i32, env, i32, i32) DEF_HELPER_3(subx_cc, i32, env, i32, i32) -DEF_HELPER_3(shl_cc, i32, env, i32, i32) -DEF_HELPER_3(shr_cc, i32, env, i32, i32) -DEF_HELPER_3(sar_cc, i32, env, i32, i32) +DEF_HELPER_3(shl8_cc, i32, env, i32, i32) +DEF_HELPER_3(shl16_cc, i32, env, i32, i32) +DEF_HELPER_3(shl32_cc, i32, env, i32, i32) +DEF_HELPER_3(shr8_cc, i32, env, i32, i32) +DEF_HELPER_3(shr16_cc, i32, env, i32, i32) +DEF_HELPER_3(shr32_cc, i32, env, i32, i32) +DEF_HELPER_3(sar8_cc, i32, env, i32, i32) +DEF_HELPER_3(sar16_cc, i32, env, i32, i32) +DEF_HELPER_3(sar32_cc, i32, env, i32, i32) DEF_HELPER_2(xflag_lt, i32, i32, i32) DEF_HELPER_2(set_sr, void, env, i32) DEF_HELPER_3(movec, void, env, i32, i32) diff --git a/target-m68k/translate.c b/target-m68k/translate.c index 8fb71b8..ecbd516 100644 --- a/target-m68k/translate.c +++ b/target-m68k/translate.c @@ -2009,6 +2009,63 @@ DISAS_INSN(addx) } /* TODO: This could be implemented without helper functions. */ +DISAS_INSN(shift8_im) +{ + TCGv reg; + int tmp; + TCGv shift; + TCGv dest; + + reg = DREG(insn, 0); + tmp = (insn >> 9) & 7; + if (tmp == 0) + tmp = 8; + shift = tcg_const_i32(tmp); + dest = tcg_temp_new_i32(); + /* No need to flush flags becuse we know we will set C flag. */ + if (insn & 0x100) { + gen_helper_shl8_cc(dest, cpu_env, reg, shift); + } else { + if (insn & 8) { + gen_helper_shr8_cc(dest, cpu_env, reg, shift); + } else { + gen_helper_sar8_cc(dest, cpu_env, reg, shift); + } + } + s->cc_op = CC_OP_SHIFTB; + gen_partset_reg(OS_BYTE, reg, dest); +} + +/* TODO: This could be implemented without helper functions. */ +DISAS_INSN(shift16_im) +{ + TCGv reg; + int tmp; + TCGv shift; + TCGv dest; + + reg = DREG(insn, 0); + tmp = (insn >> 9) & 7; + if (tmp == 0) + tmp = 8; + shift = tcg_const_i32(tmp); + dest = tcg_temp_new_i32(); + /* No need to flush flags becuse we know we will set C flag. */ + if (insn & 0x100) { + gen_helper_shl16_cc(dest, cpu_env, reg, shift); + } else { + if (insn & 8) { + gen_helper_shr16_cc(dest, cpu_env, reg, shift); + } else { + gen_helper_sar16_cc(dest, cpu_env, reg, shift); + } + } + s->cc_op = CC_OP_SHIFTW; + gen_partset_reg(OS_WORD, reg, dest); +} + + +/* TODO: This could be implemented without helper functions. */ DISAS_INSN(shift_im) { TCGv reg; @@ -2022,17 +2079,71 @@ DISAS_INSN(shift_im) shift = tcg_const_i32(tmp); /* No need to flush flags becuse we know we will set C flag. */ if (insn & 0x100) { - gen_helper_shl_cc(reg, cpu_env, reg, shift); + gen_helper_shl32_cc(reg, cpu_env, reg, shift); } else { if (insn & 8) { - gen_helper_shr_cc(reg, cpu_env, reg, shift); + gen_helper_shr32_cc(reg, cpu_env, reg, shift); } else { - gen_helper_sar_cc(reg, cpu_env, reg, shift); + gen_helper_sar32_cc(reg, cpu_env, reg, shift); } } s->cc_op = CC_OP_SHIFT; } +DISAS_INSN(shift8_reg) +{ + TCGv reg; + TCGv shift; + TCGv dest; + TCGv tmp; + + reg = DREG(insn, 0); + shift = DREG(insn, 9); + tmp = tcg_temp_new_i32(); + tcg_gen_andi_i32(tmp, shift, 63); + dest = tcg_temp_new_i32(); + /* Shift by zero leaves C flag unmodified. */ + gen_flush_flags(s); + if (insn & 0x100) { + gen_helper_shl8_cc(dest, cpu_env, reg, tmp); + } else { + if (insn & 8) { + gen_helper_shr8_cc(dest, cpu_env, reg, tmp); + } else { + gen_helper_sar8_cc(dest, cpu_env, reg, tmp); + } + } + s->cc_op = CC_OP_SHIFTB; + gen_partset_reg(OS_BYTE, reg, dest); +} + +DISAS_INSN(shift16_reg) +{ + TCGv reg; + TCGv shift; + TCGv dest; + TCGv tmp; + + reg = DREG(insn, 0); + shift = DREG(insn, 9); + tmp = tcg_temp_new_i32(); + tcg_gen_andi_i32(tmp, shift, 63); + dest = tcg_temp_new_i32(); + /* Shift by zero leaves C flag unmodified. */ + gen_flush_flags(s); + if (insn & 0x100) { + gen_helper_shl16_cc(dest, cpu_env, reg, tmp); + } else { + if (insn & 8) { + gen_helper_shr16_cc(dest, cpu_env, reg, tmp); + } else { + gen_helper_sar16_cc(dest, cpu_env, reg, tmp); + } + } + s->cc_op = CC_OP_SHIFTW; + gen_partset_reg(OS_WORD, reg, dest); +} + DISAS_INSN(shift_reg) { TCGv reg; @@ -2043,17 +2154,40 @@ DISAS_INSN(shift_reg) /* Shift by zero leaves C flag unmodified. */ gen_flush_flags(s); if (insn & 0x100) { - gen_helper_shl_cc(reg, cpu_env, reg, shift); + gen_helper_shl32_cc(reg, cpu_env, reg, shift); } else { if (insn & 8) { - gen_helper_shr_cc(reg, cpu_env, reg, shift); + gen_helper_shr32_cc(reg, cpu_env, reg, shift); } else { - gen_helper_sar_cc(reg, cpu_env, reg, shift); + gen_helper_sar32_cc(reg, cpu_env, reg, shift); } } s->cc_op = CC_OP_SHIFT; } +DISAS_INSN(shift_mem) +{ + TCGv src; + TCGv dest; + TCGv addr; + TCGv shift; + + SRC_EA(src, OS_WORD, 0, &addr); + dest = tcg_temp_new_i32(); + shift = tcg_const_i32(1); + if (insn & 0x100) { + gen_helper_shl16_cc(dest, cpu_env, src, shift); + } else { + if (insn & 8) { + gen_helper_shr16_cc(dest, cpu_env, src, shift); + } else { + gen_helper_sar16_cc(dest, cpu_env, src, shift); + } + } + s->cc_op = CC_OP_SHIFTW; + DEST_EA(insn, OS_WORD, dest, &addr); +} + DISAS_INSN(ff1) { TCGv reg; @@ -3182,8 +3316,13 @@ void register_m68k_insns (CPUM68KState *env) INSN(adda, d0c0, f0c0, M68000); INSN(shift_im, e080, f0f0, CF_ISA_A); INSN(shift_reg, e0a0, f0f0, CF_ISA_A); - INSN(shift_im, e080, f0f0, M68000); - INSN(shift_reg, e0a0, f0f0, M68000); + INSN(shift8_im, e000, f0f0, M68000); + INSN(shift16_im, e040, f0f0, M68000); + INSN(shift_im, e080, f0f0, M68000); + INSN(shift8_reg, e020, f0f0, M68000); + INSN(shift16_reg, e060, f0f0, M68000); + INSN(shift_reg, e0a0, f0f0, M68000); + INSN(shift_mem, e0c0, fcc0, M68000); INSN(undef_fpu, f000, f000, CF_ISA_A); INSN(undef_fpu, f000, f000, M68000); INSN(fpu, f200, ffc0, CF_FPU);