PCem

changeset 37:bea391e61690

Fixed lazy V flag on SHL/SHR/SAR - IBM AT & Acer 386 BIOSes work again.
author TomW
date Fri Nov 15 19:55:22 2013 +0000
parents 3150e4f3c1a3
children 79cd603440f9
files src/x86_flags.h src/x86_ops_shift.h
diffstat 2 files changed, 351 insertions(+), 276 deletions(-) [+]
line diff
     1.1 --- a/src/x86_flags.h	Sun Nov 10 16:40:52 2013 +0000
     1.2 +++ b/src/x86_flags.h	Fri Nov 15 19:55:22 2013 +0000
     1.3 @@ -12,7 +12,19 @@
     1.4          
     1.5          FLAGS_SUB8,
     1.6          FLAGS_SUB16,
     1.7 -        FLAGS_SUB32
     1.8 +        FLAGS_SUB32,
     1.9 +        
    1.10 +        FLAGS_SHL8,
    1.11 +        FLAGS_SHL16,
    1.12 +        FLAGS_SHL32,
    1.13 +
    1.14 +        FLAGS_SHR8,
    1.15 +        FLAGS_SHR16,
    1.16 +        FLAGS_SHR32,
    1.17 +
    1.18 +        FLAGS_SAR8,
    1.19 +        FLAGS_SAR16,
    1.20 +        FLAGS_SAR32,
    1.21  };
    1.22  
    1.23  static int flags_op;
    1.24 @@ -32,6 +44,15 @@
    1.25                  case FLAGS_SUB8:
    1.26                  case FLAGS_SUB16:
    1.27                  case FLAGS_SUB32:
    1.28 +                case FLAGS_SHL8:
    1.29 +                case FLAGS_SHL16:
    1.30 +                case FLAGS_SHL32:
    1.31 +                case FLAGS_SHR8:
    1.32 +                case FLAGS_SHR16:
    1.33 +                case FLAGS_SHR32:
    1.34 +                case FLAGS_SAR8:
    1.35 +                case FLAGS_SAR16:
    1.36 +                case FLAGS_SAR32:
    1.37                  return !flags_res;
    1.38                  
    1.39                  case FLAGS_UNKNOWN:
    1.40 @@ -46,16 +67,25 @@
    1.41                  case FLAGS_ZN8: 
    1.42                  case FLAGS_ADD8:
    1.43                  case FLAGS_SUB8:
    1.44 +                case FLAGS_SHL8:
    1.45 +                case FLAGS_SHR8:
    1.46 +                case FLAGS_SAR8:
    1.47                  return flags_res & 0x80;
    1.48                  
    1.49                  case FLAGS_ZN16:
    1.50                  case FLAGS_ADD16:
    1.51                  case FLAGS_SUB16:
    1.52 +                case FLAGS_SHL16:
    1.53 +                case FLAGS_SHR16:
    1.54 +                case FLAGS_SAR16:
    1.55                  return flags_res & 0x8000;
    1.56                  
    1.57                  case FLAGS_ZN32:
    1.58                  case FLAGS_ADD32:
    1.59                  case FLAGS_SUB32:
    1.60 +                case FLAGS_SHL32:
    1.61 +                case FLAGS_SHR32:
    1.62 +                case FLAGS_SAR32:
    1.63                  return flags_res & 0x80000000;
    1.64                  
    1.65                  case FLAGS_UNKNOWN:
    1.66 @@ -76,6 +106,15 @@
    1.67                  case FLAGS_SUB8:
    1.68                  case FLAGS_SUB16:
    1.69                  case FLAGS_SUB32:
    1.70 +                case FLAGS_SHL8:
    1.71 +                case FLAGS_SHL16:
    1.72 +                case FLAGS_SHL32:
    1.73 +                case FLAGS_SHR8:
    1.74 +                case FLAGS_SHR16:
    1.75 +                case FLAGS_SHR32:
    1.76 +                case FLAGS_SAR8:
    1.77 +                case FLAGS_SAR16:
    1.78 +                case FLAGS_SAR32:
    1.79                  return znptable8[flags_res & 0xff] & P_FLAG;
    1.80                  
    1.81                  case FLAGS_UNKNOWN:
    1.82 @@ -87,9 +126,12 @@
    1.83  {
    1.84          switch (flags_op)
    1.85          {
    1.86 -                case FLAGS_ZN8: 
    1.87 +                case FLAGS_ZN8:
    1.88                  case FLAGS_ZN16:
    1.89                  case FLAGS_ZN32:
    1.90 +                case FLAGS_SAR8:
    1.91 +                case FLAGS_SAR16:
    1.92 +                case FLAGS_SAR32:
    1.93                  return 0;
    1.94                  
    1.95                  case FLAGS_ADD8:
    1.96 @@ -105,7 +147,21 @@
    1.97                  return ((flags_op1 ^ flags_op2) & (flags_op1 ^ flags_res) & 0x8000);
    1.98                  case FLAGS_SUB32:
    1.99                  return ((flags_op1 ^ flags_op2) & (flags_op1 ^ flags_res) & 0x80000000);
   1.100 -                        
   1.101 +
   1.102 +                case FLAGS_SHL8:
   1.103 +                return (((flags_op1 << flags_op2) ^ (flags_op1 << (flags_op2 - 1))) & 0x80);
   1.104 +                case FLAGS_SHL16:
   1.105 +                return (((flags_op1 << flags_op2) ^ (flags_op1 << (flags_op2 - 1))) & 0x8000);
   1.106 +                case FLAGS_SHL32:
   1.107 +                return (((flags_op1 << flags_op2) ^ (flags_op1 << (flags_op2 - 1))) & 0x80000000);
   1.108 +                
   1.109 +                case FLAGS_SHR8:
   1.110 +                return ((flags_op2 == 1) && (flags_op1 & 0x80));
   1.111 +                case FLAGS_SHR16:
   1.112 +                return ((flags_op2 == 1) && (flags_op1 & 0x8000));
   1.113 +                case FLAGS_SHR32:
   1.114 +                return ((flags_op2 == 1) && (flags_op1 & 0x80000000));
   1.115 +                
   1.116                  case FLAGS_UNKNOWN:
   1.117                  return flags & V_FLAG;
   1.118          }
   1.119 @@ -118,6 +174,15 @@
   1.120                  case FLAGS_ZN8: 
   1.121                  case FLAGS_ZN16:
   1.122                  case FLAGS_ZN32:
   1.123 +                case FLAGS_SHL8:
   1.124 +                case FLAGS_SHL16:
   1.125 +                case FLAGS_SHL32:
   1.126 +                case FLAGS_SHR8:
   1.127 +                case FLAGS_SHR16:
   1.128 +                case FLAGS_SHR32:
   1.129 +                case FLAGS_SAR8:
   1.130 +                case FLAGS_SAR16:
   1.131 +                case FLAGS_SAR32:
   1.132                  return 0;
   1.133                  
   1.134                  case FLAGS_ADD8:
   1.135 @@ -214,6 +279,13 @@
   1.136          flags &= ~C_FLAG;
   1.137  }
   1.138  
   1.139 +#define set_flags_shift(op, orig, shift, res) \
   1.140 +        flags_op = op;                  \
   1.141 +        flags_res = res;                \
   1.142 +        flags_op1 = orig;               \
   1.143 +        flags_op2 = shift;              \
   1.144 +        flags &= ~C_FLAG;
   1.145 +
   1.146  static inline void setadd8(uint8_t a, uint8_t b)
   1.147  {
   1.148          flags_op1 = a;
     2.1 --- a/src/x86_ops_shift.h	Sun Nov 10 16:40:52 2013 +0000
     2.2 +++ b/src/x86_ops_shift.h	Fri Nov 15 19:55:22 2013 +0000
     2.3 @@ -1,280 +1,283 @@
     2.4 -#define OP_SHIFT_b(c)                                                           \
     2.5 -        if (!c) return 0;                                                       \
     2.6 -        flags_rebuild();                                                        \
     2.7 -        switch (rmdat & 0x38)                                                   \
     2.8 -        {                                                                       \
     2.9 -                case 0x00: /*ROL b, c*/                                         \
    2.10 -                while (c > 0)                                                   \
    2.11 -                {                                                               \
    2.12 -                        temp2 = (temp & 0x80) ? 1 : 0;                          \
    2.13 -                        temp = (temp << 1) | temp2;                             \
    2.14 -                        c--;                                                    \
    2.15 -                }                                                               \
    2.16 -                seteab(temp);           if (abrt) return 0;                     \
    2.17 -                flags &= ~(C_FLAG | V_FLAG);                                    \
    2.18 -                if (temp2) flags |= C_FLAG;                                     \
    2.19 -                if ((flags & C_FLAG) ^ (temp >> 7)) flags |= V_FLAG;            \
    2.20 -                cycles -= ((mod == 3) ? 3 : 7);                                 \
    2.21 -                break;                                                          \
    2.22 -                case 0x08: /*ROR b,CL*/                                         \
    2.23 -                while (c > 0)                                                   \
    2.24 -                {                                                               \
    2.25 -                        temp2 = temp & 1;                                       \
    2.26 -                        temp >>= 1;                                             \
    2.27 -                        if (temp2) temp |= 0x80;                                \
    2.28 -                        c--;                                                    \
    2.29 -                }                                                               \
    2.30 -                seteab(temp);           if (abrt) return 0;                     \
    2.31 -                flags &= ~(C_FLAG | V_FLAG);                                    \
    2.32 -                if (temp2) flags |= C_FLAG;                                     \
    2.33 -                if ((temp ^ (temp >> 1)) & 0x40) flags |= V_FLAG;               \
    2.34 -                cycles -= ((mod == 3) ? 3 : 7);                                 \
    2.35 -                break;                                                          \
    2.36 -                case 0x10: /*RCL b,CL*/                                         \
    2.37 -                temp2 = flags & C_FLAG;                                         \
    2.38 -                while (c > 0)                                                   \
    2.39 -                {                                                               \
    2.40 -                        tempc = temp2 ? 1 : 0;                                  \
    2.41 -                        temp2 = temp & 0x80;                                    \
    2.42 -                        temp = (temp << 1) | tempc;                             \
    2.43 -                        c--;                                                    \
    2.44 -                        if (is486) cycles--;                                    \
    2.45 -                }                                                               \
    2.46 -                seteab(temp);           if (abrt) return 0;                     \
    2.47 -                flags &= ~(C_FLAG | V_FLAG);                                    \
    2.48 -                if (temp2) flags |= C_FLAG;                                     \
    2.49 -                if ((flags & C_FLAG) ^ (temp >> 7)) flags |= V_FLAG;            \
    2.50 -                cycles -= ((mod == 3) ? 9 : 10);                                \
    2.51 -                break;                                                          \
    2.52 -                case 0x18: /*RCR b,CL*/                                         \
    2.53 -                temp2 = flags & C_FLAG;                                         \
    2.54 -                while (c > 0)                                                   \
    2.55 -                {                                                               \
    2.56 -                        tempc = temp2 ? 0x80 : 0;                               \
    2.57 -                        temp2 = temp & 1;                                       \
    2.58 -                        temp = (temp >> 1) | tempc;                             \
    2.59 -                        c--;                                                    \
    2.60 -                        if (is486) cycles--;                                    \
    2.61 -                }                                                               \
    2.62 -                seteab(temp);           if (abrt) return 0;                     \
    2.63 -                flags &= ~(C_FLAG | V_FLAG);                                    \
    2.64 -                if (temp2) flags |= C_FLAG;                                     \
    2.65 -                if ((temp ^ (temp >> 1)) & 0x40) flags |= V_FLAG;               \
    2.66 -                cycles -= ((mod == 3) ? 9 : 10);                                \
    2.67 -                break;                                                          \
    2.68 -                case 0x20: case 0x30: /*SHL b,CL*/                              \
    2.69 -                seteab(temp << c);      if (abrt) return 0;                     \
    2.70 -                setznp8(temp << c);                                             \
    2.71 -                if ((temp << (c - 1)) & 0x80) flags |= C_FLAG;                  \
    2.72 -                if (((temp << c) ^ (temp << (c - 1))) & 0x80) flags |= V_FLAG;  \
    2.73 -                cycles -= ((mod == 3) ? 3 : 7);                                 \
    2.74 -                break;                                                          \
    2.75 -                case 0x28: /*SHR b,CL*/                                         \
    2.76 -                seteab(temp >> c);      if (abrt) return 0;                     \
    2.77 -                setznp8(temp >> c);                                             \
    2.78 -                if ((temp >> (c - 1)) & 1) flags |= C_FLAG;                     \
    2.79 -                if (c == 1 && temp & 0x80) flags |= V_FLAG;                     \
    2.80 -                cycles -= ((mod == 3) ? 3 : 7);                                 \
    2.81 -                break;                                                          \
    2.82 -                case 0x38: /*SAR b,CL*/                                         \
    2.83 -                tempc = ((temp >> (c - 1)) & 1);                                \
    2.84 -                while (c > 0)                                                   \
    2.85 -                {                                                               \
    2.86 -                        temp >>= 1;                                             \
    2.87 -                        if (temp & 0x40) temp |= 0x80;                          \
    2.88 -                        c--;                                                    \
    2.89 -                }                                                               \
    2.90 -                seteab(temp);           if (abrt) return 0;                     \
    2.91 -                setznp8(temp);                                                  \
    2.92 -                if (tempc) flags |= C_FLAG;                                     \
    2.93 -                cycles -= ((mod == 3) ? 3 : 7);                                 \
    2.94 -                break;                                                          \
    2.95 +#define OP_SHIFT_b(c)                                                                   \
    2.96 +        {                                                                               \
    2.97 +                uint8_t temp_orig = temp;                                               \
    2.98 +                if (!c) return 0;                                                       \
    2.99 +                flags_rebuild();                                                        \
   2.100 +                switch (rmdat & 0x38)                                                   \
   2.101 +                {                                                                       \
   2.102 +                        case 0x00: /*ROL b, c*/                                         \
   2.103 +                        while (c > 0)                                                   \
   2.104 +                        {                                                               \
   2.105 +                                temp2 = (temp & 0x80) ? 1 : 0;                          \
   2.106 +                                temp = (temp << 1) | temp2;                             \
   2.107 +                                c--;                                                    \
   2.108 +                        }                                                               \
   2.109 +                        seteab(temp);           if (abrt) return 0;                     \
   2.110 +                        flags &= ~(C_FLAG | V_FLAG);                                    \
   2.111 +                        if (temp2) flags |= C_FLAG;                                     \
   2.112 +                        if ((flags & C_FLAG) ^ (temp >> 7)) flags |= V_FLAG;            \
   2.113 +                        cycles -= ((mod == 3) ? 3 : 7);                                 \
   2.114 +                        break;                                                          \
   2.115 +                        case 0x08: /*ROR b,CL*/                                         \
   2.116 +                        while (c > 0)                                                   \
   2.117 +                        {                                                               \
   2.118 +                                temp2 = temp & 1;                                       \
   2.119 +                                temp >>= 1;                                             \
   2.120 +                                if (temp2) temp |= 0x80;                                \
   2.121 +                                c--;                                                    \
   2.122 +                        }                                                               \
   2.123 +                        seteab(temp);           if (abrt) return 0;                     \
   2.124 +                        flags &= ~(C_FLAG | V_FLAG);                                    \
   2.125 +                        if (temp2) flags |= C_FLAG;                                     \
   2.126 +                        if ((temp ^ (temp >> 1)) & 0x40) flags |= V_FLAG;               \
   2.127 +                        cycles -= ((mod == 3) ? 3 : 7);                                 \
   2.128 +                        break;                                                          \
   2.129 +                        case 0x10: /*RCL b,CL*/                                         \
   2.130 +                        temp2 = flags & C_FLAG;                                         \
   2.131 +                        while (c > 0)                                                   \
   2.132 +                        {                                                               \
   2.133 +                                tempc = temp2 ? 1 : 0;                                  \
   2.134 +                                temp2 = temp & 0x80;                                    \
   2.135 +                                temp = (temp << 1) | tempc;                             \
   2.136 +                                c--;                                                    \
   2.137 +                                if (is486) cycles--;                                    \
   2.138 +                        }                                                               \
   2.139 +                        seteab(temp);           if (abrt) return 0;                     \
   2.140 +                        flags &= ~(C_FLAG | V_FLAG);                                    \
   2.141 +                        if (temp2) flags |= C_FLAG;                                     \
   2.142 +                        if ((flags & C_FLAG) ^ (temp >> 7)) flags |= V_FLAG;            \
   2.143 +                        cycles -= ((mod == 3) ? 9 : 10);                                \
   2.144 +                        break;                                                          \
   2.145 +                        case 0x18: /*RCR b,CL*/                                         \
   2.146 +                        temp2 = flags & C_FLAG;                                         \
   2.147 +                        while (c > 0)                                                   \
   2.148 +                        {                                                               \
   2.149 +                                tempc = temp2 ? 0x80 : 0;                               \
   2.150 +                                temp2 = temp & 1;                                       \
   2.151 +                                temp = (temp >> 1) | tempc;                             \
   2.152 +                                c--;                                                    \
   2.153 +                                if (is486) cycles--;                                    \
   2.154 +                        }                                                               \
   2.155 +                        seteab(temp);           if (abrt) return 0;                     \
   2.156 +                        flags &= ~(C_FLAG | V_FLAG);                                    \
   2.157 +                        if (temp2) flags |= C_FLAG;                                     \
   2.158 +                        if ((temp ^ (temp >> 1)) & 0x40) flags |= V_FLAG;               \
   2.159 +                        cycles -= ((mod == 3) ? 9 : 10);                                \
   2.160 +                        break;                                                          \
   2.161 +                        case 0x20: case 0x30: /*SHL b,CL*/                              \
   2.162 +                        seteab(temp << c);      if (abrt) return 0;                     \
   2.163 +                        set_flags_shift(FLAGS_SHL8, temp_orig, c, temp << c);           \
   2.164 +                        if ((temp << (c - 1)) & 0x80) flags |= C_FLAG;                  \
   2.165 +                        cycles -= ((mod == 3) ? 3 : 7);                                 \
   2.166 +                        break;                                                          \
   2.167 +                        case 0x28: /*SHR b,CL*/                                         \
   2.168 +                        seteab(temp >> c);      if (abrt) return 0;                     \
   2.169 +                        set_flags_shift(FLAGS_SHR8, temp_orig, c, temp >> c);           \
   2.170 +                        if ((temp >> (c - 1)) & 1) flags |= C_FLAG;                     \
   2.171 +                        cycles -= ((mod == 3) ? 3 : 7);                                 \
   2.172 +                        break;                                                          \
   2.173 +                        case 0x38: /*SAR b,CL*/                                         \
   2.174 +                        tempc = ((temp >> (c - 1)) & 1);                                \
   2.175 +                        while (c > 0)                                                   \
   2.176 +                        {                                                               \
   2.177 +                                temp >>= 1;                                             \
   2.178 +                                if (temp & 0x40) temp |= 0x80;                          \
   2.179 +                                c--;                                                    \
   2.180 +                        }                                                               \
   2.181 +                        seteab(temp);           if (abrt) return 0;                     \
   2.182 +                        set_flags_shift(FLAGS_SAR8, temp_orig, c, temp);                \
   2.183 +                        if (tempc) flags |= C_FLAG;                                     \
   2.184 +                        cycles -= ((mod == 3) ? 3 : 7);                                 \
   2.185 +                        break;                                                          \
   2.186 +                }                                                                       \
   2.187          }
   2.188  
   2.189 -#define OP_SHIFT_w(c)                                                           \
   2.190 -        if (!c) return 0;                                                       \
   2.191 -        flags_rebuild();                                                        \
   2.192 -        switch (rmdat & 0x38)                                                   \
   2.193 -        {                                                                       \
   2.194 -                case 0x00: /*ROL w, c*/                                         \
   2.195 -                while (c > 0)                                                   \
   2.196 -                {                                                               \
   2.197 -                        temp2 = (temp & 0x8000) ? 1 : 0;                        \
   2.198 -                        temp = (temp << 1) | temp2;                             \
   2.199 -                        c--;                                                    \
   2.200 -                }                                                               \
   2.201 -                seteaw(temp);           if (abrt) return 0;                     \
   2.202 -                flags &= ~(C_FLAG | V_FLAG);                                    \
   2.203 -                if (temp2) flags |= C_FLAG;                                     \
   2.204 -                if ((flags & C_FLAG) ^ (temp >> 15)) flags |= V_FLAG;           \
   2.205 -                cycles -= ((mod == 3) ? 3 : 7);                                 \
   2.206 -                break;                                                          \
   2.207 -                case 0x08: /*ROR w, c*/                                         \
   2.208 -                while (c > 0)                                                   \
   2.209 -                {                                                               \
   2.210 -                        temp2 = temp & 1;                                       \
   2.211 -                        temp >>= 1;                                             \
   2.212 -                        if (temp2) temp |= 0x8000;                              \
   2.213 -                        c--;                                                    \
   2.214 -                }                                                               \
   2.215 -                seteaw(temp);           if (abrt) return 0;                     \
   2.216 -                flags &= ~(C_FLAG | V_FLAG);                                    \
   2.217 -                if (temp2) flags |= C_FLAG;                                     \
   2.218 -                if ((temp ^ (temp >> 1)) & 0x4000) flags |= V_FLAG;             \
   2.219 -                cycles -= ((mod == 3) ? 3 : 7);                                 \
   2.220 -                break;                                                          \
   2.221 -                case 0x10: /*RCL w, c*/                                         \
   2.222 -                temp2 = flags & C_FLAG;                                         \
   2.223 -                while (c > 0)                                                   \
   2.224 -                {                                                               \
   2.225 -                        tempc = temp2 ? 1 : 0;                                  \
   2.226 -                        temp2 = temp & 0x8000;                                  \
   2.227 -                        temp = (temp << 1) | tempc;                             \
   2.228 -                        c--;                                                    \
   2.229 -                        if (is486) cycles--;                                    \
   2.230 -                }                                                               \
   2.231 -                seteaw(temp);           if (abrt) return 0;                     \
   2.232 -                flags &= ~(C_FLAG | V_FLAG);                                    \
   2.233 -                if (temp2) flags |= C_FLAG;                                     \
   2.234 -                if ((flags & C_FLAG) ^ (temp >> 15)) flags |= V_FLAG;           \
   2.235 -                cycles -= ((mod == 3) ? 9 : 10);                                \
   2.236 -                break;                                                          \
   2.237 -                case 0x18: /*RCR w, c*/                                         \
   2.238 -                temp2 = flags & C_FLAG;                                         \
   2.239 -                while (c > 0)                                                   \
   2.240 -                {                                                               \
   2.241 -                        tempc = temp2 ? 0x8000 : 0;                             \
   2.242 -                        temp2 = temp & 1;                                       \
   2.243 -                        temp = (temp >> 1) | tempc;                             \
   2.244 -                        c--;                                                    \
   2.245 -                        if (is486) cycles--;                                    \
   2.246 -                }                                                               \
   2.247 -                seteaw(temp);           if (abrt) return 0;                     \
   2.248 -                flags &= ~(C_FLAG | V_FLAG);                                    \
   2.249 -                if (temp2) flags |= C_FLAG;                                     \
   2.250 -                if ((temp ^ (temp >> 1)) & 0x4000) flags |= V_FLAG;             \
   2.251 -                cycles -= ((mod == 3) ? 9 : 10);                                \
   2.252 -                break;                                                          \
   2.253 -                case 0x20: case 0x30: /*SHL w, c*/                              \
   2.254 -                seteaw(temp << c);      if (abrt) return 0;                     \
   2.255 -                setznp16(temp << c);                                            \
   2.256 -                if ((temp << (c - 1)) & 0x8000) flags |= C_FLAG;                \
   2.257 -                if (((temp << c) ^ (temp << (c - 1))) & 0x8000) flags |= V_FLAG;\
   2.258 -                cycles -= ((mod == 3) ? 3 : 7);                                 \
   2.259 -                break;                                                          \
   2.260 -                case 0x28: /*SHR w, c*/                                         \
   2.261 -                seteaw(temp >> c);      if (abrt) return 0;                     \
   2.262 -                setznp16(temp >> c);                                            \
   2.263 -                if ((temp >> (c - 1)) & 1) flags |= C_FLAG;                     \
   2.264 -                if (c == 1 && temp & 0x8000) flags |= V_FLAG;                   \
   2.265 -                cycles -= ((mod == 3) ? 3 : 7);                                 \
   2.266 -                break;                                                          \
   2.267 -                case 0x38: /*SAR w, c*/                                         \
   2.268 -                tempc = ((temp >> (c - 1)) & 1);                                \
   2.269 -                while (c > 0)                                                   \
   2.270 -                {                                                               \
   2.271 -                        temp >>= 1;                                             \
   2.272 -                        if (temp & 0x4000) temp |= 0x8000;                      \
   2.273 -                        c--;                                                    \
   2.274 -                }                                                               \
   2.275 -                seteaw(temp);           if (abrt) return 0;                     \
   2.276 -                setznp16(temp);                                                 \
   2.277 -                if (tempc) flags |= C_FLAG;                                     \
   2.278 -                cycles -= ((mod == 3) ? 3 : 7);                                 \
   2.279 -                break;                                                          \
   2.280 +#define OP_SHIFT_w(c)                                                                   \
   2.281 +        {                                                                               \
   2.282 +                uint16_t temp_orig = temp;                                              \
   2.283 +                if (!c) return 0;                                                       \
   2.284 +                flags_rebuild();                                                        \
   2.285 +                switch (rmdat & 0x38)                                                   \
   2.286 +                {                                                                       \
   2.287 +                        case 0x00: /*ROL w, c*/                                         \
   2.288 +                        while (c > 0)                                                   \
   2.289 +                        {                                                               \
   2.290 +                                temp2 = (temp & 0x8000) ? 1 : 0;                        \
   2.291 +                                temp = (temp << 1) | temp2;                             \
   2.292 +                                c--;                                                    \
   2.293 +                        }                                                               \
   2.294 +                        seteaw(temp);           if (abrt) return 0;                     \
   2.295 +                        flags &= ~(C_FLAG | V_FLAG);                                    \
   2.296 +                        if (temp2) flags |= C_FLAG;                                     \
   2.297 +                        if ((flags & C_FLAG) ^ (temp >> 15)) flags |= V_FLAG;           \
   2.298 +                        cycles -= ((mod == 3) ? 3 : 7);                                 \
   2.299 +                        break;                                                          \
   2.300 +                        case 0x08: /*ROR w, c*/                                         \
   2.301 +                        while (c > 0)                                                   \
   2.302 +                        {                                                               \
   2.303 +                                temp2 = temp & 1;                                       \
   2.304 +                                temp >>= 1;                                             \
   2.305 +                                if (temp2) temp |= 0x8000;                              \
   2.306 +                                c--;                                                    \
   2.307 +                        }                                                               \
   2.308 +                        seteaw(temp);           if (abrt) return 0;                     \
   2.309 +                        flags &= ~(C_FLAG | V_FLAG);                                    \
   2.310 +                        if (temp2) flags |= C_FLAG;                                     \
   2.311 +                        if ((temp ^ (temp >> 1)) & 0x4000) flags |= V_FLAG;             \
   2.312 +                        cycles -= ((mod == 3) ? 3 : 7);                                 \
   2.313 +                        break;                                                          \
   2.314 +                        case 0x10: /*RCL w, c*/                                         \
   2.315 +                        temp2 = flags & C_FLAG;                                         \
   2.316 +                        while (c > 0)                                                   \
   2.317 +                        {                                                               \
   2.318 +                                tempc = temp2 ? 1 : 0;                                  \
   2.319 +                                temp2 = temp & 0x8000;                                  \
   2.320 +                                temp = (temp << 1) | tempc;                             \
   2.321 +                                c--;                                                    \
   2.322 +                                if (is486) cycles--;                                    \
   2.323 +                        }                                                               \
   2.324 +                        seteaw(temp);           if (abrt) return 0;                     \
   2.325 +                        flags &= ~(C_FLAG | V_FLAG);                                    \
   2.326 +                        if (temp2) flags |= C_FLAG;                                     \
   2.327 +                        if ((flags & C_FLAG) ^ (temp >> 15)) flags |= V_FLAG;           \
   2.328 +                        cycles -= ((mod == 3) ? 9 : 10);                                \
   2.329 +                        break;                                                          \
   2.330 +                        case 0x18: /*RCR w, c*/                                         \
   2.331 +                        temp2 = flags & C_FLAG;                                         \
   2.332 +                        while (c > 0)                                                   \
   2.333 +                        {                                                               \
   2.334 +                                tempc = temp2 ? 0x8000 : 0;                             \
   2.335 +                                temp2 = temp & 1;                                       \
   2.336 +                                temp = (temp >> 1) | tempc;                             \
   2.337 +                                c--;                                                    \
   2.338 +                                if (is486) cycles--;                                    \
   2.339 +                        }                                                               \
   2.340 +                        seteaw(temp);           if (abrt) return 0;                     \
   2.341 +                        flags &= ~(C_FLAG | V_FLAG);                                    \
   2.342 +                        if (temp2) flags |= C_FLAG;                                     \
   2.343 +                        if ((temp ^ (temp >> 1)) & 0x4000) flags |= V_FLAG;             \
   2.344 +                        cycles -= ((mod == 3) ? 9 : 10);                                \
   2.345 +                        break;                                                          \
   2.346 +                        case 0x20: case 0x30: /*SHL w, c*/                              \
   2.347 +                        seteaw(temp << c);      if (abrt) return 0;                     \
   2.348 +                        set_flags_shift(FLAGS_SHL16, temp_orig, c, temp << c);          \
   2.349 +                        if ((temp << (c - 1)) & 0x8000) flags |= C_FLAG;                \
   2.350 +                        cycles -= ((mod == 3) ? 3 : 7);                                 \
   2.351 +                        break;                                                          \
   2.352 +                        case 0x28: /*SHR w, c*/                                         \
   2.353 +                        seteaw(temp >> c);      if (abrt) return 0;                     \
   2.354 +                        set_flags_shift(FLAGS_SHR16, temp_orig, c, temp >> c);          \
   2.355 +                        if ((temp >> (c - 1)) & 1) flags |= C_FLAG;                     \
   2.356 +                        cycles -= ((mod == 3) ? 3 : 7);                                 \
   2.357 +                        break;                                                          \
   2.358 +                        case 0x38: /*SAR w, c*/                                         \
   2.359 +                        tempc = ((temp >> (c - 1)) & 1);                                \
   2.360 +                        while (c > 0)                                                   \
   2.361 +                        {                                                               \
   2.362 +                                temp >>= 1;                                             \
   2.363 +                                if (temp & 0x4000) temp |= 0x8000;                      \
   2.364 +                                c--;                                                    \
   2.365 +                        }                                                               \
   2.366 +                        seteaw(temp);           if (abrt) return 0;                     \
   2.367 +                        set_flags_shift(FLAGS_SAR16, temp_orig, c, temp);               \
   2.368 +                        if (tempc) flags |= C_FLAG;                                     \
   2.369 +                        cycles -= ((mod == 3) ? 3 : 7);                                 \
   2.370 +                        break;                                                          \
   2.371 +                }                                                                       \
   2.372          }
   2.373  
   2.374 -#define OP_SHIFT_l(c)                                                           \
   2.375 -        if (!c) return 0;                                                       \
   2.376 -        flags_rebuild();                                                        \
   2.377 -        switch (rmdat & 0x38)                                                   \
   2.378 -        {                                                                       \
   2.379 -                case 0x00: /*ROL l, c*/                                         \
   2.380 -                while (c > 0)                                                   \
   2.381 -                {                                                               \
   2.382 -                        temp2 = (temp & 0x80000000) ? 1 : 0;                    \
   2.383 -                        temp = (temp << 1) | temp2;                             \
   2.384 -                        c--;                                                    \
   2.385 -                }                                                               \
   2.386 -                seteal(temp);           if (abrt) return 0;                     \
   2.387 -                flags &= ~(C_FLAG | V_FLAG);                                    \
   2.388 -                if (temp2) flags |= C_FLAG;                                     \
   2.389 -                if ((flags & C_FLAG) ^ (temp >> 31)) flags |= V_FLAG;           \
   2.390 -                cycles -= ((mod == 3) ? 3 : 7);                                 \
   2.391 -                break;                                                          \
   2.392 -                case 0x08: /*ROR l, c*/                                         \
   2.393 -                while (c > 0)                                                   \
   2.394 -                {                                                               \
   2.395 -                        temp2 = temp & 1;                                       \
   2.396 -                        temp >>= 1;                                             \
   2.397 -                        if (temp2) temp |= 0x80000000;                          \
   2.398 -                        c--;                                                    \
   2.399 -                }                                                               \
   2.400 -                seteal(temp);           if (abrt) return 0;                     \
   2.401 -                flags &= ~(C_FLAG | V_FLAG);                                    \
   2.402 -                if (temp2) flags |= C_FLAG;                                     \
   2.403 -                if ((temp ^ (temp >> 1)) & 0x40000000) flags |= V_FLAG;         \
   2.404 -                cycles -= ((mod == 3) ? 3 : 7);                                 \
   2.405 -                break;                                                          \
   2.406 -                case 0x10: /*RCL l, c*/                                         \
   2.407 -                temp2 = flags & C_FLAG;                                         \
   2.408 -                while (c > 0)                                                   \
   2.409 -                {                                                               \
   2.410 -                        tempc = temp2 ? 1 : 0;                                  \
   2.411 -                        temp2 = temp & 0x80000000;                              \
   2.412 -                        temp = (temp << 1) | tempc;                             \
   2.413 -                        c--;                                                    \
   2.414 -                        if (is486) cycles--;                                    \
   2.415 -                }                                                               \
   2.416 -                seteal(temp);           if (abrt) return 0;                     \
   2.417 -                flags &= ~(C_FLAG | V_FLAG);                                    \
   2.418 -                if (temp2) flags |= C_FLAG;                                     \
   2.419 -                if ((flags & C_FLAG) ^ (temp >> 31)) flags |= V_FLAG;           \
   2.420 -                cycles -= ((mod == 3) ? 9 : 10);                                \
   2.421 -                break;                                                          \
   2.422 -                case 0x18: /*RCR l, c*/                                         \
   2.423 -                temp2 = flags & C_FLAG;                                         \
   2.424 -                while (c > 0)                                                   \
   2.425 -                {                                                               \
   2.426 -                        tempc = temp2 ? 0x80000000 : 0;                         \
   2.427 -                        temp2 = temp & 1;                                       \
   2.428 -                        temp = (temp >> 1) | tempc;                             \
   2.429 -                        c--;                                                    \
   2.430 -                        if (is486) cycles--;                                    \
   2.431 -                }                                                               \
   2.432 -                seteal(temp);           if (abrt) return 0;                     \
   2.433 -                flags &= ~(C_FLAG | V_FLAG);                                    \
   2.434 -                if (temp2) flags |= C_FLAG;                                     \
   2.435 -                if ((temp ^ (temp >> 1)) & 0x40000000) flags |= V_FLAG;         \
   2.436 -                cycles -= ((mod == 3) ? 9 : 10);                                \
   2.437 -                break;                                                          \
   2.438 -                case 0x20: case 0x30: /*SHL l, c*/                              \
   2.439 -                seteal(temp << c);      if (abrt) return 0;                     \
   2.440 -                setznp32(temp << c);                                            \
   2.441 -                if ((temp << (c - 1)) & 0x80000000) flags |= C_FLAG;            \
   2.442 -                if (((temp << c) ^ (temp << (c - 1))) & 0x80000000) flags |= V_FLAG;\
   2.443 -                cycles -= ((mod == 3) ? 3 : 7);                                 \
   2.444 -                break;                                                          \
   2.445 -                case 0x28: /*SHR l, c*/                                         \
   2.446 -                seteal(temp >> c);      if (abrt) return 0;                     \
   2.447 -                setznp32(temp >> c);                                            \
   2.448 -                if ((temp >> (c - 1)) & 1) flags |= C_FLAG;                     \
   2.449 -                if (c == 1 && temp & 0x80000000) flags |= V_FLAG;               \
   2.450 -                cycles -= ((mod == 3) ? 3 : 7);                                 \
   2.451 -                break;                                                          \
   2.452 -                case 0x38: /*SAR l, c*/                                         \
   2.453 -                tempc = ((temp >> (c - 1)) & 1);                                \
   2.454 -                while (c > 0)                                                   \
   2.455 -                {                                                               \
   2.456 -                        temp >>= 1;                                             \
   2.457 -                        if (temp & 0x40000000) temp |= 0x80000000;              \
   2.458 -                        c--;                                                    \
   2.459 -                }                                                               \
   2.460 -                seteal(temp);           if (abrt) return 0;                     \
   2.461 -                setznp32(temp);                                                 \
   2.462 -                if (tempc) flags |= C_FLAG;                                     \
   2.463 -                cycles -= ((mod == 3) ? 3 : 7);                                 \
   2.464 -                break;                                                          \
   2.465 +#define OP_SHIFT_l(c)                                                                   \
   2.466 +        {                                                                               \
   2.467 +                uint32_t temp_orig = temp;                                              \
   2.468 +                if (!c) return 0;                                                       \
   2.469 +                flags_rebuild();                                                        \
   2.470 +                switch (rmdat & 0x38)                                                   \
   2.471 +                {                                                                       \
   2.472 +                        case 0x00: /*ROL l, c*/                                         \
   2.473 +                        while (c > 0)                                                   \
   2.474 +                        {                                                               \
   2.475 +                                temp2 = (temp & 0x80000000) ? 1 : 0;                    \
   2.476 +                                temp = (temp << 1) | temp2;                             \
   2.477 +                                c--;                                                    \
   2.478 +                        }                                                               \
   2.479 +                        seteal(temp);           if (abrt) return 0;                     \
   2.480 +                        flags &= ~(C_FLAG | V_FLAG);                                    \
   2.481 +                        if (temp2) flags |= C_FLAG;                                     \
   2.482 +                        if ((flags & C_FLAG) ^ (temp >> 31)) flags |= V_FLAG;           \
   2.483 +                        cycles -= ((mod == 3) ? 3 : 7);                                 \
   2.484 +                        break;                                                          \
   2.485 +                        case 0x08: /*ROR l, c*/                                         \
   2.486 +                        while (c > 0)                                                   \
   2.487 +                        {                                                               \
   2.488 +                                temp2 = temp & 1;                                       \
   2.489 +                                temp >>= 1;                                             \
   2.490 +                                if (temp2) temp |= 0x80000000;                          \
   2.491 +                                c--;                                                    \
   2.492 +                        }                                                               \
   2.493 +                        seteal(temp);           if (abrt) return 0;                     \
   2.494 +                        flags &= ~(C_FLAG | V_FLAG);                                    \
   2.495 +                        if (temp2) flags |= C_FLAG;                                     \
   2.496 +                        if ((temp ^ (temp >> 1)) & 0x40000000) flags |= V_FLAG;         \
   2.497 +                        cycles -= ((mod == 3) ? 3 : 7);                                 \
   2.498 +                        break;                                                          \
   2.499 +                        case 0x10: /*RCL l, c*/                                         \
   2.500 +                        temp2 = flags & C_FLAG;                                         \
   2.501 +                        while (c > 0)                                                   \
   2.502 +                        {                                                               \
   2.503 +                                tempc = temp2 ? 1 : 0;                                  \
   2.504 +                                temp2 = temp & 0x80000000;                              \
   2.505 +                                temp = (temp << 1) | tempc;                             \
   2.506 +                                c--;                                                    \
   2.507 +                                if (is486) cycles--;                                    \
   2.508 +                        }                                                               \
   2.509 +                        seteal(temp);           if (abrt) return 0;                     \
   2.510 +                        flags &= ~(C_FLAG | V_FLAG);                                    \
   2.511 +                        if (temp2) flags |= C_FLAG;                                     \
   2.512 +                        if ((flags & C_FLAG) ^ (temp >> 31)) flags |= V_FLAG;           \
   2.513 +                        cycles -= ((mod == 3) ? 9 : 10);                                \
   2.514 +                        break;                                                          \
   2.515 +                        case 0x18: /*RCR l, c*/                                         \
   2.516 +                        temp2 = flags & C_FLAG;                                         \
   2.517 +                        while (c > 0)                                                   \
   2.518 +                        {                                                               \
   2.519 +                                tempc = temp2 ? 0x80000000 : 0;                         \
   2.520 +                                temp2 = temp & 1;                                       \
   2.521 +                                temp = (temp >> 1) | tempc;                             \
   2.522 +                                c--;                                                    \
   2.523 +                                if (is486) cycles--;                                    \
   2.524 +                        }                                                               \
   2.525 +                        seteal(temp);           if (abrt) return 0;                     \
   2.526 +                        flags &= ~(C_FLAG | V_FLAG);                                    \
   2.527 +                        if (temp2) flags |= C_FLAG;                                     \
   2.528 +                        if ((temp ^ (temp >> 1)) & 0x40000000) flags |= V_FLAG;         \
   2.529 +                        cycles -= ((mod == 3) ? 9 : 10);                                \
   2.530 +                        break;                                                          \
   2.531 +                        case 0x20: case 0x30: /*SHL l, c*/                              \
   2.532 +                        seteal(temp << c);      if (abrt) return 0;                     \
   2.533 +                        set_flags_shift(FLAGS_SHL32, temp_orig, c, temp << c);          \
   2.534 +                        if ((temp << (c - 1)) & 0x80000000) flags |= C_FLAG;            \
   2.535 +                        cycles -= ((mod == 3) ? 3 : 7);                                 \
   2.536 +                        break;                                                          \
   2.537 +                        case 0x28: /*SHR l, c*/                                         \
   2.538 +                        seteal(temp >> c);      if (abrt) return 0;                     \
   2.539 +                        set_flags_shift(FLAGS_SHR32, temp_orig, c, temp >> c);          \
   2.540 +                        if ((temp >> (c - 1)) & 1) flags |= C_FLAG;                     \
   2.541 +                        cycles -= ((mod == 3) ? 3 : 7);                                 \
   2.542 +                        break;                                                          \
   2.543 +                        case 0x38: /*SAR l, c*/                                         \
   2.544 +                        tempc = ((temp >> (c - 1)) & 1);                                \
   2.545 +                        while (c > 0)                                                   \
   2.546 +                        {                                                               \
   2.547 +                                temp >>= 1;                                             \
   2.548 +                                if (temp & 0x40000000) temp |= 0x80000000;              \
   2.549 +                                c--;                                                    \
   2.550 +                        }                                                               \
   2.551 +                        seteal(temp);           if (abrt) return 0;                     \
   2.552 +                        set_flags_shift(FLAGS_SAR32, temp_orig, c, temp);               \
   2.553 +                        if (tempc) flags |= C_FLAG;                                     \
   2.554 +                        cycles -= ((mod == 3) ? 3 : 7);                                 \
   2.555 +                        break;                                                          \
   2.556 +                }                                                                       \
   2.557          }
   2.558  
   2.559  static int opC0_a16(uint32_t fetchdat)