@@ -327,8 +327,7 @@ void cpu_m68k_flush_flags(CPUM68KState *env, int cc_op)
#define SET_FLAGS_SHIFT(type) do { \
SET_NZ(dest, type); \
- if (src) \
- flags |= CCF_C; \
+ flags |= src; \
} while(0)
flags = 0;
@@ -751,7 +750,7 @@ uint32_t HELPER(glue(glue(shl, bits),_cc))(CPUState *env, uint32_t val, uint32_t
result = 0; \
cf = 0; \
} \
- env->cc_src = cf; \
+ env->cc_src = cf ? CCF_C : 0; \
if (shift) env->cc_x = (cf != 0); \
env->cc_dest = result; \
return result; \
@@ -780,7 +779,7 @@ uint32_t HELPER(glue(glue(shr, bits), _cc))(CPUState *env, uint32_t val, uint32_
result = 0; \
cf = 0; \
} \
- env->cc_src = cf; \
+ env->cc_src = cf ? CCF_C : 0; \
if (shift) env->cc_x = (cf != 0); \
env->cc_dest = result; \
return result; \
@@ -790,6 +789,46 @@ HELPER_SHR(uint8_t, 8)
HELPER_SHR(uint16_t, 16)
HELPER_SHR(uint32_t, 32)
+#define HELPER_SAL(type, bits) \
+uint32_t HELPER(glue(glue(sal, bits),_cc))(CPUState *env, uint32_t val, uint32_t shift) \
+{ \
+ type result; \
+ uint32_t cf; \
+ uint32_t vf; \
+ uint32_t m; \
+ shift &= 63; \
+ if (shift == 0) { \
+ vf = 0; \
+ } else if (shift < bits) { \
+ m = ((1llu << (shift + 1)) - 1) << (bits - shift - 1); \
+ vf = (val & m) != m && (val & m) != 0; \
+ } else {\
+ m = (1llu << bits) - 1; \
+ vf = (val & m) != 0; \
+ }\
+ 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 ? CCF_C : 0) | (vf ? CCF_V : 0); \
+ if (shift) env->cc_x = (cf != 0); \
+ env->cc_dest = result; \
+ return result; \
+}
+
+HELPER_SAL(int8_t, 8)
+HELPER_SAL(int16_t, 16)
+HELPER_SAL(int32_t, 32)
+
#define HELPER_SAR(type, bits) \
uint32_t HELPER(glue(glue(sar, bits), _cc))(CPUState *env, uint32_t val, uint32_t shift) \
{ \
@@ -806,7 +845,7 @@ uint32_t HELPER(glue(glue(sar, bits), _cc))(CPUState *env, uint32_t val, uint32_
result = (type)val >> (bits - 1); \
cf = (type)val >> (bits - 1); \
} \
- env->cc_src = cf; \
+ env->cc_src = cf ? CCF_C : 0; \
if (shift) env->cc_x = (cf != 0); \
env->cc_dest = result; \
return result; \
@@ -26,6 +26,9 @@ 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(sal8_cc, i32, env, i32, i32)
+DEF_HELPER_3(sal16_cc, i32, env, i32, i32)
+DEF_HELPER_3(sal32_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)
@@ -2298,7 +2298,11 @@ DISAS_INSN(shift8_im)
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);
+ if (insn & 8) {
+ gen_helper_shl8_cc(dest, cpu_env, reg, shift);
+ } else {
+ gen_helper_sal8_cc(dest, cpu_env, reg, shift);
+ }
} else {
if (insn & 8) {
gen_helper_shr8_cc(dest, cpu_env, reg, shift);
@@ -2326,7 +2330,11 @@ DISAS_INSN(shift16_im)
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);
+ if (insn & 8) {
+ gen_helper_shl16_cc(dest, cpu_env, reg, shift);
+ } else {
+ gen_helper_sal16_cc(dest, cpu_env, reg, shift);
+ }
} else {
if (insn & 8) {
gen_helper_shr16_cc(dest, cpu_env, reg, shift);
@@ -2353,7 +2361,11 @@ 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_shl32_cc(reg, cpu_env, reg, shift);
+ if (insn & 8) {
+ gen_helper_shl32_cc(reg, cpu_env, reg, shift);
+ } else {
+ gen_helper_sal32_cc(reg, cpu_env, reg, shift);
+ }
} else {
if (insn & 8) {
gen_helper_shr32_cc(reg, cpu_env, reg, shift);
@@ -2379,7 +2391,11 @@ DISAS_INSN(shift8_reg)
/* Shift by zero leaves C flag unmodified. */
gen_flush_flags(s);
if (insn & 0x100) {
- gen_helper_shl8_cc(dest, cpu_env, reg, tmp);
+ if (insn & 8) {
+ gen_helper_shl8_cc(dest, cpu_env, reg, tmp);
+ } else {
+ gen_helper_sal8_cc(dest, cpu_env, reg, tmp);
+ }
} else {
if (insn & 8) {
gen_helper_shr8_cc(dest, cpu_env, reg, tmp);
@@ -2406,7 +2422,11 @@ DISAS_INSN(shift16_reg)
/* Shift by zero leaves C flag unmodified. */
gen_flush_flags(s);
if (insn & 0x100) {
- gen_helper_shl16_cc(dest, cpu_env, reg, tmp);
+ if (insn & 8) {
+ gen_helper_shl16_cc(dest, cpu_env, reg, tmp);
+ } else {
+ gen_helper_sal16_cc(dest, cpu_env, reg, tmp);
+ }
} else {
if (insn & 8) {
gen_helper_shr16_cc(dest, cpu_env, reg, tmp);
@@ -2428,7 +2448,11 @@ DISAS_INSN(shift_reg)
/* Shift by zero leaves C flag unmodified. */
gen_flush_flags(s);
if (insn & 0x100) {
- gen_helper_shl32_cc(reg, cpu_env, reg, shift);
+ if (insn & 8) {
+ gen_helper_shl32_cc(reg, cpu_env, reg, shift);
+ } else {
+ gen_helper_sal32_cc(reg, cpu_env, reg, shift);
+ }
} else {
if (insn & 8) {
gen_helper_shr32_cc(reg, cpu_env, reg, shift);