bellard | b6abf97 | 2008-05-17 12:44:31 +0000 | [diff] [blame] | 1 | /* |
Blue Swirl | 38de4c4 | 2012-05-12 20:39:26 +0000 | [diff] [blame] | 2 | * x86 condition code helpers |
bellard | b6abf97 | 2008-05-17 12:44:31 +0000 | [diff] [blame] | 3 | * |
| 4 | * Copyright (c) 2008 Fabrice Bellard |
| 5 | * |
| 6 | * This library is free software; you can redistribute it and/or |
| 7 | * modify it under the terms of the GNU Lesser General Public |
| 8 | * License as published by the Free Software Foundation; either |
| 9 | * version 2 of the License, or (at your option) any later version. |
| 10 | * |
| 11 | * This library is distributed in the hope that it will be useful, |
| 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| 14 | * Lesser General Public License for more details. |
| 15 | * |
| 16 | * You should have received a copy of the GNU Lesser General Public |
Blue Swirl | 8167ee8 | 2009-07-16 20:47:01 +0000 | [diff] [blame] | 17 | * License along with this library; if not, see <http://www.gnu.org/licenses/>. |
bellard | b6abf97 | 2008-05-17 12:44:31 +0000 | [diff] [blame] | 18 | */ |
Blue Swirl | a04759f | 2012-04-29 12:27:33 +0000 | [diff] [blame] | 19 | |
bellard | b6abf97 | 2008-05-17 12:44:31 +0000 | [diff] [blame] | 20 | #define DATA_BITS (1 << (3 + SHIFT)) |
bellard | b6abf97 | 2008-05-17 12:44:31 +0000 | [diff] [blame] | 21 | |
| 22 | #if DATA_BITS == 8 |
| 23 | #define SUFFIX b |
| 24 | #define DATA_TYPE uint8_t |
bellard | b6abf97 | 2008-05-17 12:44:31 +0000 | [diff] [blame] | 25 | #elif DATA_BITS == 16 |
| 26 | #define SUFFIX w |
| 27 | #define DATA_TYPE uint16_t |
bellard | b6abf97 | 2008-05-17 12:44:31 +0000 | [diff] [blame] | 28 | #elif DATA_BITS == 32 |
| 29 | #define SUFFIX l |
| 30 | #define DATA_TYPE uint32_t |
bellard | b6abf97 | 2008-05-17 12:44:31 +0000 | [diff] [blame] | 31 | #elif DATA_BITS == 64 |
| 32 | #define SUFFIX q |
| 33 | #define DATA_TYPE uint64_t |
bellard | b6abf97 | 2008-05-17 12:44:31 +0000 | [diff] [blame] | 34 | #else |
| 35 | #error unhandled operand size |
| 36 | #endif |
| 37 | |
Richard Henderson | 8601c0b | 2013-01-23 16:06:38 -0800 | [diff] [blame] | 38 | #define SIGN_MASK (((DATA_TYPE)1) << (DATA_BITS - 1)) |
| 39 | |
bellard | 07d2c59 | 2008-05-17 13:57:33 +0000 | [diff] [blame] | 40 | /* dynamic flags computation */ |
| 41 | |
Richard Henderson | 8601c0b | 2013-01-23 16:06:38 -0800 | [diff] [blame] | 42 | static int glue(compute_all_add, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1) |
bellard | 07d2c59 | 2008-05-17 13:57:33 +0000 | [diff] [blame] | 43 | { |
| 44 | int cf, pf, af, zf, sf, of; |
Richard Henderson | 8601c0b | 2013-01-23 16:06:38 -0800 | [diff] [blame] | 45 | DATA_TYPE src2 = dst - src1; |
Blue Swirl | a04759f | 2012-04-29 12:27:33 +0000 | [diff] [blame] | 46 | |
Richard Henderson | 8601c0b | 2013-01-23 16:06:38 -0800 | [diff] [blame] | 47 | cf = dst < src1; |
| 48 | pf = parity_table[(uint8_t)dst]; |
| 49 | af = (dst ^ src1 ^ src2) & CC_A; |
| 50 | zf = (dst == 0) * CC_Z; |
| 51 | sf = lshift(dst, 8 - DATA_BITS) & CC_S; |
| 52 | of = lshift((src1 ^ src2 ^ -1) & (src1 ^ dst), 12 - DATA_BITS) & CC_O; |
bellard | 07d2c59 | 2008-05-17 13:57:33 +0000 | [diff] [blame] | 53 | return cf | pf | af | zf | sf | of; |
| 54 | } |
| 55 | |
Richard Henderson | 8601c0b | 2013-01-23 16:06:38 -0800 | [diff] [blame] | 56 | static int glue(compute_c_add, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1) |
bellard | 07d2c59 | 2008-05-17 13:57:33 +0000 | [diff] [blame] | 57 | { |
Richard Henderson | 8601c0b | 2013-01-23 16:06:38 -0800 | [diff] [blame] | 58 | return dst < src1; |
bellard | 07d2c59 | 2008-05-17 13:57:33 +0000 | [diff] [blame] | 59 | } |
| 60 | |
Richard Henderson | 988c3eb | 2013-01-23 16:03:16 -0800 | [diff] [blame] | 61 | static int glue(compute_all_adc, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1, |
| 62 | DATA_TYPE src3) |
bellard | 07d2c59 | 2008-05-17 13:57:33 +0000 | [diff] [blame] | 63 | { |
| 64 | int cf, pf, af, zf, sf, of; |
Richard Henderson | 988c3eb | 2013-01-23 16:03:16 -0800 | [diff] [blame] | 65 | DATA_TYPE src2 = dst - src1 - src3; |
Blue Swirl | a04759f | 2012-04-29 12:27:33 +0000 | [diff] [blame] | 66 | |
Richard Henderson | 988c3eb | 2013-01-23 16:03:16 -0800 | [diff] [blame] | 67 | cf = (src3 ? dst <= src1 : dst < src1); |
Richard Henderson | 8601c0b | 2013-01-23 16:06:38 -0800 | [diff] [blame] | 68 | pf = parity_table[(uint8_t)dst]; |
| 69 | af = (dst ^ src1 ^ src2) & 0x10; |
| 70 | zf = (dst == 0) << 6; |
| 71 | sf = lshift(dst, 8 - DATA_BITS) & 0x80; |
| 72 | of = lshift((src1 ^ src2 ^ -1) & (src1 ^ dst), 12 - DATA_BITS) & CC_O; |
bellard | 07d2c59 | 2008-05-17 13:57:33 +0000 | [diff] [blame] | 73 | return cf | pf | af | zf | sf | of; |
| 74 | } |
| 75 | |
Richard Henderson | 988c3eb | 2013-01-23 16:03:16 -0800 | [diff] [blame] | 76 | static int glue(compute_c_adc, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1, |
| 77 | DATA_TYPE src3) |
bellard | 07d2c59 | 2008-05-17 13:57:33 +0000 | [diff] [blame] | 78 | { |
Richard Henderson | 988c3eb | 2013-01-23 16:03:16 -0800 | [diff] [blame] | 79 | return src3 ? dst <= src1 : dst < src1; |
bellard | 07d2c59 | 2008-05-17 13:57:33 +0000 | [diff] [blame] | 80 | } |
| 81 | |
Richard Henderson | 8601c0b | 2013-01-23 16:06:38 -0800 | [diff] [blame] | 82 | static int glue(compute_all_sub, SUFFIX)(DATA_TYPE dst, DATA_TYPE src2) |
bellard | 07d2c59 | 2008-05-17 13:57:33 +0000 | [diff] [blame] | 83 | { |
| 84 | int cf, pf, af, zf, sf, of; |
Richard Henderson | 8601c0b | 2013-01-23 16:06:38 -0800 | [diff] [blame] | 85 | DATA_TYPE src1 = dst + src2; |
Blue Swirl | a04759f | 2012-04-29 12:27:33 +0000 | [diff] [blame] | 86 | |
Richard Henderson | 8601c0b | 2013-01-23 16:06:38 -0800 | [diff] [blame] | 87 | cf = src1 < src2; |
| 88 | pf = parity_table[(uint8_t)dst]; |
| 89 | af = (dst ^ src1 ^ src2) & CC_A; |
| 90 | zf = (dst == 0) * CC_Z; |
| 91 | sf = lshift(dst, 8 - DATA_BITS) & CC_S; |
| 92 | of = lshift((src1 ^ src2) & (src1 ^ dst), 12 - DATA_BITS) & CC_O; |
bellard | 07d2c59 | 2008-05-17 13:57:33 +0000 | [diff] [blame] | 93 | return cf | pf | af | zf | sf | of; |
| 94 | } |
| 95 | |
Richard Henderson | 8601c0b | 2013-01-23 16:06:38 -0800 | [diff] [blame] | 96 | static int glue(compute_c_sub, SUFFIX)(DATA_TYPE dst, DATA_TYPE src2) |
bellard | 07d2c59 | 2008-05-17 13:57:33 +0000 | [diff] [blame] | 97 | { |
Richard Henderson | 8601c0b | 2013-01-23 16:06:38 -0800 | [diff] [blame] | 98 | DATA_TYPE src1 = dst + src2; |
Blue Swirl | a04759f | 2012-04-29 12:27:33 +0000 | [diff] [blame] | 99 | |
Richard Henderson | 8601c0b | 2013-01-23 16:06:38 -0800 | [diff] [blame] | 100 | return src1 < src2; |
bellard | 07d2c59 | 2008-05-17 13:57:33 +0000 | [diff] [blame] | 101 | } |
| 102 | |
Richard Henderson | 988c3eb | 2013-01-23 16:03:16 -0800 | [diff] [blame] | 103 | static int glue(compute_all_sbb, SUFFIX)(DATA_TYPE dst, DATA_TYPE src2, |
| 104 | DATA_TYPE src3) |
bellard | 07d2c59 | 2008-05-17 13:57:33 +0000 | [diff] [blame] | 105 | { |
| 106 | int cf, pf, af, zf, sf, of; |
Richard Henderson | 988c3eb | 2013-01-23 16:03:16 -0800 | [diff] [blame] | 107 | DATA_TYPE src1 = dst + src2 + src3; |
Blue Swirl | a04759f | 2012-04-29 12:27:33 +0000 | [diff] [blame] | 108 | |
Richard Henderson | 988c3eb | 2013-01-23 16:03:16 -0800 | [diff] [blame] | 109 | cf = (src3 ? src1 <= src2 : src1 < src2); |
Richard Henderson | 8601c0b | 2013-01-23 16:06:38 -0800 | [diff] [blame] | 110 | pf = parity_table[(uint8_t)dst]; |
| 111 | af = (dst ^ src1 ^ src2) & 0x10; |
| 112 | zf = (dst == 0) << 6; |
| 113 | sf = lshift(dst, 8 - DATA_BITS) & 0x80; |
| 114 | of = lshift((src1 ^ src2) & (src1 ^ dst), 12 - DATA_BITS) & CC_O; |
bellard | 07d2c59 | 2008-05-17 13:57:33 +0000 | [diff] [blame] | 115 | return cf | pf | af | zf | sf | of; |
| 116 | } |
| 117 | |
Richard Henderson | 988c3eb | 2013-01-23 16:03:16 -0800 | [diff] [blame] | 118 | static int glue(compute_c_sbb, SUFFIX)(DATA_TYPE dst, DATA_TYPE src2, |
| 119 | DATA_TYPE src3) |
bellard | 07d2c59 | 2008-05-17 13:57:33 +0000 | [diff] [blame] | 120 | { |
Richard Henderson | 988c3eb | 2013-01-23 16:03:16 -0800 | [diff] [blame] | 121 | DATA_TYPE src1 = dst + src2 + src3; |
Blue Swirl | a04759f | 2012-04-29 12:27:33 +0000 | [diff] [blame] | 122 | |
Richard Henderson | 988c3eb | 2013-01-23 16:03:16 -0800 | [diff] [blame] | 123 | return (src3 ? src1 <= src2 : src1 < src2); |
bellard | 07d2c59 | 2008-05-17 13:57:33 +0000 | [diff] [blame] | 124 | } |
| 125 | |
Richard Henderson | 8601c0b | 2013-01-23 16:06:38 -0800 | [diff] [blame] | 126 | static int glue(compute_all_logic, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1) |
bellard | 07d2c59 | 2008-05-17 13:57:33 +0000 | [diff] [blame] | 127 | { |
| 128 | int cf, pf, af, zf, sf, of; |
Blue Swirl | a04759f | 2012-04-29 12:27:33 +0000 | [diff] [blame] | 129 | |
bellard | 07d2c59 | 2008-05-17 13:57:33 +0000 | [diff] [blame] | 130 | cf = 0; |
Richard Henderson | 8601c0b | 2013-01-23 16:06:38 -0800 | [diff] [blame] | 131 | pf = parity_table[(uint8_t)dst]; |
bellard | 07d2c59 | 2008-05-17 13:57:33 +0000 | [diff] [blame] | 132 | af = 0; |
Richard Henderson | 8601c0b | 2013-01-23 16:06:38 -0800 | [diff] [blame] | 133 | zf = (dst == 0) * CC_Z; |
| 134 | sf = lshift(dst, 8 - DATA_BITS) & CC_S; |
bellard | 07d2c59 | 2008-05-17 13:57:33 +0000 | [diff] [blame] | 135 | of = 0; |
| 136 | return cf | pf | af | zf | sf | of; |
| 137 | } |
| 138 | |
Richard Henderson | 8601c0b | 2013-01-23 16:06:38 -0800 | [diff] [blame] | 139 | static int glue(compute_all_inc, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1) |
bellard | 07d2c59 | 2008-05-17 13:57:33 +0000 | [diff] [blame] | 140 | { |
| 141 | int cf, pf, af, zf, sf, of; |
Richard Henderson | 8601c0b | 2013-01-23 16:06:38 -0800 | [diff] [blame] | 142 | DATA_TYPE src2; |
Blue Swirl | a04759f | 2012-04-29 12:27:33 +0000 | [diff] [blame] | 143 | |
Richard Henderson | 8601c0b | 2013-01-23 16:06:38 -0800 | [diff] [blame] | 144 | cf = src1; |
| 145 | src1 = dst - 1; |
bellard | 07d2c59 | 2008-05-17 13:57:33 +0000 | [diff] [blame] | 146 | src2 = 1; |
Richard Henderson | 8601c0b | 2013-01-23 16:06:38 -0800 | [diff] [blame] | 147 | pf = parity_table[(uint8_t)dst]; |
| 148 | af = (dst ^ src1 ^ src2) & CC_A; |
| 149 | zf = (dst == 0) * CC_Z; |
| 150 | sf = lshift(dst, 8 - DATA_BITS) & CC_S; |
| 151 | of = (dst == SIGN_MASK) * CC_O; |
bellard | 07d2c59 | 2008-05-17 13:57:33 +0000 | [diff] [blame] | 152 | return cf | pf | af | zf | sf | of; |
| 153 | } |
| 154 | |
Richard Henderson | 8601c0b | 2013-01-23 16:06:38 -0800 | [diff] [blame] | 155 | static int glue(compute_all_dec, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1) |
bellard | 07d2c59 | 2008-05-17 13:57:33 +0000 | [diff] [blame] | 156 | { |
| 157 | int cf, pf, af, zf, sf, of; |
Richard Henderson | 8601c0b | 2013-01-23 16:06:38 -0800 | [diff] [blame] | 158 | DATA_TYPE src2; |
Blue Swirl | a04759f | 2012-04-29 12:27:33 +0000 | [diff] [blame] | 159 | |
Richard Henderson | 8601c0b | 2013-01-23 16:06:38 -0800 | [diff] [blame] | 160 | cf = src1; |
| 161 | src1 = dst + 1; |
bellard | 07d2c59 | 2008-05-17 13:57:33 +0000 | [diff] [blame] | 162 | src2 = 1; |
Richard Henderson | 8601c0b | 2013-01-23 16:06:38 -0800 | [diff] [blame] | 163 | pf = parity_table[(uint8_t)dst]; |
| 164 | af = (dst ^ src1 ^ src2) & CC_A; |
| 165 | zf = (dst == 0) * CC_Z; |
| 166 | sf = lshift(dst, 8 - DATA_BITS) & CC_S; |
| 167 | of = (dst == SIGN_MASK - 1) * CC_O; |
bellard | 07d2c59 | 2008-05-17 13:57:33 +0000 | [diff] [blame] | 168 | return cf | pf | af | zf | sf | of; |
| 169 | } |
| 170 | |
Richard Henderson | 8601c0b | 2013-01-23 16:06:38 -0800 | [diff] [blame] | 171 | static int glue(compute_all_shl, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1) |
bellard | 07d2c59 | 2008-05-17 13:57:33 +0000 | [diff] [blame] | 172 | { |
| 173 | int cf, pf, af, zf, sf, of; |
Blue Swirl | a04759f | 2012-04-29 12:27:33 +0000 | [diff] [blame] | 174 | |
Richard Henderson | 8601c0b | 2013-01-23 16:06:38 -0800 | [diff] [blame] | 175 | cf = (src1 >> (DATA_BITS - 1)) & CC_C; |
| 176 | pf = parity_table[(uint8_t)dst]; |
bellard | 07d2c59 | 2008-05-17 13:57:33 +0000 | [diff] [blame] | 177 | af = 0; /* undefined */ |
Richard Henderson | 8601c0b | 2013-01-23 16:06:38 -0800 | [diff] [blame] | 178 | zf = (dst == 0) * CC_Z; |
| 179 | sf = lshift(dst, 8 - DATA_BITS) & CC_S; |
| 180 | /* of is defined iff shift count == 1 */ |
| 181 | of = lshift(src1 ^ dst, 12 - DATA_BITS) & CC_O; |
bellard | 07d2c59 | 2008-05-17 13:57:33 +0000 | [diff] [blame] | 182 | return cf | pf | af | zf | sf | of; |
| 183 | } |
| 184 | |
Richard Henderson | 8601c0b | 2013-01-23 16:06:38 -0800 | [diff] [blame] | 185 | static int glue(compute_c_shl, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1) |
bellard | 07d2c59 | 2008-05-17 13:57:33 +0000 | [diff] [blame] | 186 | { |
Richard Henderson | 8601c0b | 2013-01-23 16:06:38 -0800 | [diff] [blame] | 187 | return (src1 >> (DATA_BITS - 1)) & CC_C; |
bellard | 07d2c59 | 2008-05-17 13:57:33 +0000 | [diff] [blame] | 188 | } |
| 189 | |
Richard Henderson | 8601c0b | 2013-01-23 16:06:38 -0800 | [diff] [blame] | 190 | static int glue(compute_all_sar, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1) |
bellard | 07d2c59 | 2008-05-17 13:57:33 +0000 | [diff] [blame] | 191 | { |
| 192 | int cf, pf, af, zf, sf, of; |
Blue Swirl | a04759f | 2012-04-29 12:27:33 +0000 | [diff] [blame] | 193 | |
Richard Henderson | 8601c0b | 2013-01-23 16:06:38 -0800 | [diff] [blame] | 194 | cf = src1 & 1; |
| 195 | pf = parity_table[(uint8_t)dst]; |
bellard | 07d2c59 | 2008-05-17 13:57:33 +0000 | [diff] [blame] | 196 | af = 0; /* undefined */ |
Richard Henderson | 8601c0b | 2013-01-23 16:06:38 -0800 | [diff] [blame] | 197 | zf = (dst == 0) * CC_Z; |
| 198 | sf = lshift(dst, 8 - DATA_BITS) & CC_S; |
| 199 | /* of is defined iff shift count == 1 */ |
| 200 | of = lshift(src1 ^ dst, 12 - DATA_BITS) & CC_O; |
bellard | 07d2c59 | 2008-05-17 13:57:33 +0000 | [diff] [blame] | 201 | return cf | pf | af | zf | sf | of; |
| 202 | } |
| 203 | |
bellard | 07d2c59 | 2008-05-17 13:57:33 +0000 | [diff] [blame] | 204 | /* NOTE: we compute the flags like the P4. On olders CPUs, only OF and |
Richard Henderson | 8601c0b | 2013-01-23 16:06:38 -0800 | [diff] [blame] | 205 | CF are modified and it is slower to do that. Note as well that we |
| 206 | don't truncate SRC1 for computing carry to DATA_TYPE. */ |
| 207 | static int glue(compute_all_mul, SUFFIX)(DATA_TYPE dst, target_long src1) |
bellard | 07d2c59 | 2008-05-17 13:57:33 +0000 | [diff] [blame] | 208 | { |
| 209 | int cf, pf, af, zf, sf, of; |
Blue Swirl | a04759f | 2012-04-29 12:27:33 +0000 | [diff] [blame] | 210 | |
Richard Henderson | 8601c0b | 2013-01-23 16:06:38 -0800 | [diff] [blame] | 211 | cf = (src1 != 0); |
| 212 | pf = parity_table[(uint8_t)dst]; |
bellard | 07d2c59 | 2008-05-17 13:57:33 +0000 | [diff] [blame] | 213 | af = 0; /* undefined */ |
Richard Henderson | 8601c0b | 2013-01-23 16:06:38 -0800 | [diff] [blame] | 214 | zf = (dst == 0) * CC_Z; |
| 215 | sf = lshift(dst, 8 - DATA_BITS) & CC_S; |
| 216 | of = cf * CC_O; |
bellard | 07d2c59 | 2008-05-17 13:57:33 +0000 | [diff] [blame] | 217 | return cf | pf | af | zf | sf | of; |
| 218 | } |
| 219 | |
Richard Henderson | bc4b43d | 2013-01-23 16:44:37 -0800 | [diff] [blame] | 220 | static int glue(compute_all_bmilg, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1) |
| 221 | { |
| 222 | int cf, pf, af, zf, sf, of; |
| 223 | |
| 224 | cf = (src1 == 0); |
| 225 | pf = 0; /* undefined */ |
| 226 | af = 0; /* undefined */ |
| 227 | zf = (dst == 0) * CC_Z; |
| 228 | sf = lshift(dst, 8 - DATA_BITS) & CC_S; |
| 229 | of = 0; |
| 230 | return cf | pf | af | zf | sf | of; |
| 231 | } |
| 232 | |
| 233 | static int glue(compute_c_bmilg, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1) |
| 234 | { |
| 235 | return src1 == 0; |
| 236 | } |
| 237 | |
bellard | b6abf97 | 2008-05-17 12:44:31 +0000 | [diff] [blame] | 238 | #undef DATA_BITS |
bellard | b6abf97 | 2008-05-17 12:44:31 +0000 | [diff] [blame] | 239 | #undef SIGN_MASK |
| 240 | #undef DATA_TYPE |
bellard | b6abf97 | 2008-05-17 12:44:31 +0000 | [diff] [blame] | 241 | #undef DATA_MASK |
| 242 | #undef SUFFIX |