1 /* 2 * i386 helpers 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 17 * License along with this library; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA 19 */ 20 #define DATA_BITS (1 << (3 + SHIFT)) 21 #define SHIFT_MASK (DATA_BITS - 1) 22 #define SIGN_MASK (((target_ulong)1) << (DATA_BITS - 1)) 23 #if DATA_BITS <= 32 24 #define SHIFT1_MASK 0x1f 25 #else 26 #define SHIFT1_MASK 0x3f 27 #endif 28 29 #if DATA_BITS == 8 30 #define SUFFIX b 31 #define DATA_TYPE uint8_t 32 #define DATA_STYPE int8_t 33 #define DATA_MASK 0xff 34 #elif DATA_BITS == 16 35 #define SUFFIX w 36 #define DATA_TYPE uint16_t 37 #define DATA_STYPE int16_t 38 #define DATA_MASK 0xffff 39 #elif DATA_BITS == 32 40 #define SUFFIX l 41 #define DATA_TYPE uint32_t 42 #define DATA_STYPE int32_t 43 #define DATA_MASK 0xffffffff 44 #elif DATA_BITS == 64 45 #define SUFFIX q 46 #define DATA_TYPE uint64_t 47 #define DATA_STYPE int64_t 48 #define DATA_MASK 0xffffffffffffffffULL 49 #else 50 #error unhandled operand size 51 #endif 52 53 /* shifts */ 54 55 target_ulong glue(helper_rcl, SUFFIX)(CPUX86State *env, 56 target_ulong t0, target_ulong t1) 57 { 58 int count, eflags; 59 target_ulong src; 60 target_long res; 61 62 count = t1 & SHIFT1_MASK; 63 #if DATA_BITS == 16 64 count = rclw_table[count]; 65 #elif DATA_BITS == 8 66 count = rclb_table[count]; 67 #endif 68 if (count) { 69 eflags = env->cc_src; 70 t0 &= DATA_MASK; 71 src = t0; 72 res = (t0 << count) | ((target_ulong)(eflags & CC_C) << (count - 1)); 73 if (count > 1) 74 res |= t0 >> (DATA_BITS + 1 - count); 75 t0 = res; 76 env->cc_src = (eflags & ~(CC_C | CC_O)) | 77 (lshift(src ^ t0, 11 - (DATA_BITS - 1)) & CC_O) | 78 ((src >> (DATA_BITS - count)) & CC_C); 79 } 80 return t0; 81 } 82 83 target_ulong glue(helper_rcr, SUFFIX)(CPUX86State *env, 84 target_ulong t0, target_ulong t1) 85 { 86 int count, eflags; 87 target_ulong src; 88 target_long res; 89 90 count = t1 & SHIFT1_MASK; 91 #if DATA_BITS == 16 92 count = rclw_table[count]; 93 #elif DATA_BITS == 8 94 count = rclb_table[count]; 95 #endif 96 if (count) { 97 eflags = env->cc_src; 98 t0 &= DATA_MASK; 99 src = t0; 100 res = (t0 >> count) | ((target_ulong)(eflags & CC_C) << (DATA_BITS - count)); 101 if (count > 1) 102 res |= t0 << (DATA_BITS + 1 - count); 103 t0 = res; 104 env->cc_src = (eflags & ~(CC_C | CC_O)) | 105 (lshift(src ^ t0, 11 - (DATA_BITS - 1)) & CC_O) | 106 ((src >> (count - 1)) & CC_C); 107 } 108 return t0; 109 } 110 111 #undef DATA_BITS 112 #undef SHIFT_MASK 113 #undef SHIFT1_MASK 114 #undef SIGN_MASK 115 #undef DATA_TYPE 116 #undef DATA_STYPE 117 #undef DATA_MASK 118 #undef SUFFIX 119