1/* udis86 - libudis86/syn-intel.c 2 * 3 * Copyright (c) 2002-2009 Vivek Thampi 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without modification, 7 * are permitted provided that the following conditions are met: 8 * 9 * * Redistributions of source code must retain the above copyright notice, 10 * this list of conditions and the following disclaimer. 11 * * Redistributions in binary form must reproduce the above copyright notice, 12 * this list of conditions and the following disclaimer in the documentation 13 * and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 19 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 22 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26#include "config.h" 27 28#if USE(UDIS86) 29 30#include "udis86_types.h" 31#include "udis86_extern.h" 32#include "udis86_decode.h" 33#include "udis86_itab.h" 34#include "udis86_syn.h" 35 36/* ----------------------------------------------------------------------------- 37 * opr_cast() - Prints an operand cast. 38 * ----------------------------------------------------------------------------- 39 */ 40static void 41opr_cast(struct ud* u, struct ud_operand* op) 42{ 43 switch(op->size) { 44 case 8: mkasm(u, "byte " ); break; 45 case 16: mkasm(u, "word " ); break; 46 case 32: mkasm(u, "dword "); break; 47 case 64: mkasm(u, "qword "); break; 48 case 80: mkasm(u, "tword "); break; 49 default: break; 50 } 51 if (u->br_far) 52 mkasm(u, "far "); 53} 54 55/* ----------------------------------------------------------------------------- 56 * gen_operand() - Generates assembly output for each operand. 57 * ----------------------------------------------------------------------------- 58 */ 59static void gen_operand(struct ud* u, struct ud_operand* op, int syn_cast) 60{ 61 switch(op->type) { 62 case UD_OP_REG: 63 mkasm(u, "%s", ud_reg_tab[op->base - UD_R_AL]); 64 break; 65 66 case UD_OP_MEM: { 67 68 int op_f = 0; 69 70 if (syn_cast) 71 opr_cast(u, op); 72 73 mkasm(u, "["); 74 75 if (u->pfx_seg) 76 mkasm(u, "%s:", ud_reg_tab[u->pfx_seg - UD_R_AL]); 77 78 if (op->base) { 79 mkasm(u, "%s", ud_reg_tab[op->base - UD_R_AL]); 80 op_f = 1; 81 } 82 83 if (op->index) { 84 if (op_f) 85 mkasm(u, "+"); 86 mkasm(u, "%s", ud_reg_tab[op->index - UD_R_AL]); 87 op_f = 1; 88 } 89 90 if (op->scale) 91 mkasm(u, "*%d", op->scale); 92 93 if (op->offset == 8) { 94 if (op->lval.sbyte < 0) 95 mkasm(u, "-0x%x", -op->lval.sbyte); 96 else mkasm(u, "%s0x%x", (op_f) ? "+" : "", op->lval.sbyte); 97 } 98 else if (op->offset == 16) 99 mkasm(u, "%s0x%x", (op_f) ? "+" : "", op->lval.uword); 100 else if (op->offset == 32) { 101 if (u->adr_mode == 64) { 102 if (op->lval.sdword < 0) 103 mkasm(u, "-0x%x", -op->lval.sdword); 104 else mkasm(u, "%s0x%x", (op_f) ? "+" : "", op->lval.sdword); 105 } 106 else mkasm(u, "%s0x%lx", (op_f) ? "+" : "", (unsigned long)op->lval.udword); 107 } 108 else if (op->offset == 64) 109 mkasm(u, "%s0x" FMT64 "x", (op_f) ? "+" : "", op->lval.uqword); 110 111 mkasm(u, "]"); 112 break; 113 } 114 115 case UD_OP_IMM: { 116 int64_t imm = 0; 117 uint64_t sext_mask = 0xffffffffffffffffull; 118 unsigned sext_size = op->size; 119 120 if (syn_cast) 121 opr_cast(u, op); 122 switch (op->size) { 123 case 8: imm = op->lval.sbyte; break; 124 case 16: imm = op->lval.sword; break; 125 case 32: imm = op->lval.sdword; break; 126 case 64: imm = op->lval.sqword; break; 127 } 128 if ( P_SEXT( u->itab_entry->prefix ) ) { 129 sext_size = u->operand[ 0 ].size; 130 if ( u->mnemonic == UD_Ipush ) 131 /* push sign-extends to operand size */ 132 sext_size = u->opr_mode; 133 } 134 if ( sext_size < 64 ) 135 sext_mask = ( 1ull << sext_size ) - 1; 136 mkasm( u, "0x" FMT64 "x", imm & sext_mask ); 137 138 break; 139 } 140 141 142 case UD_OP_JIMM: 143 if (syn_cast) opr_cast(u, op); 144 switch (op->size) { 145 case 8: 146 mkasm(u, "0x" FMT64 "x", u->pc + op->lval.sbyte); 147 break; 148 case 16: 149 mkasm(u, "0x" FMT64 "x", ( u->pc + op->lval.sword ) & 0xffff ); 150 break; 151 case 32: 152 mkasm(u, "0x" FMT64 "x", ( u->pc + op->lval.sdword ) & 0xfffffffful ); 153 break; 154 default:break; 155 } 156 break; 157 158 case UD_OP_PTR: 159 switch (op->size) { 160 case 32: 161 mkasm(u, "word 0x%x:0x%x", op->lval.ptr.seg, 162 op->lval.ptr.off & 0xFFFF); 163 break; 164 case 48: 165 mkasm(u, "dword 0x%x:0x%lx", op->lval.ptr.seg, 166 (unsigned long)op->lval.ptr.off); 167 break; 168 } 169 break; 170 171 case UD_OP_CONST: 172 if (syn_cast) opr_cast(u, op); 173 mkasm(u, "%d", op->lval.udword); 174 break; 175 176 default: return; 177 } 178} 179 180/* ============================================================================= 181 * translates to intel syntax 182 * ============================================================================= 183 */ 184extern void ud_translate_intel(struct ud* u) 185{ 186 /* -- prefixes -- */ 187 188 /* check if P_OSO prefix is used */ 189 if (! P_OSO(u->itab_entry->prefix) && u->pfx_opr) { 190 switch (u->dis_mode) { 191 case 16: 192 mkasm(u, "o32 "); 193 break; 194 case 32: 195 case 64: 196 mkasm(u, "o16 "); 197 break; 198 } 199 } 200 201 /* check if P_ASO prefix was used */ 202 if (! P_ASO(u->itab_entry->prefix) && u->pfx_adr) { 203 switch (u->dis_mode) { 204 case 16: 205 mkasm(u, "a32 "); 206 break; 207 case 32: 208 mkasm(u, "a16 "); 209 break; 210 case 64: 211 mkasm(u, "a32 "); 212 break; 213 } 214 } 215 216 if ( u->pfx_seg && 217 u->operand[0].type != UD_OP_MEM && 218 u->operand[1].type != UD_OP_MEM ) { 219 mkasm(u, "%s ", ud_reg_tab[u->pfx_seg - UD_R_AL]); 220 } 221 if (u->pfx_lock) 222 mkasm(u, "lock "); 223 if (u->pfx_rep) 224 mkasm(u, "rep "); 225 if (u->pfx_repne) 226 mkasm(u, "repne "); 227 228 /* print the instruction mnemonic */ 229 mkasm(u, "%s ", ud_lookup_mnemonic(u->mnemonic)); 230 231 /* operand 1 */ 232 if (u->operand[0].type != UD_NONE) { 233 int cast = 0; 234 if ( u->operand[0].type == UD_OP_IMM && 235 u->operand[1].type == UD_NONE ) 236 cast = u->c1; 237 if ( u->operand[0].type == UD_OP_MEM ) { 238 cast = u->c1; 239 if ( u->operand[1].type == UD_OP_IMM || 240 u->operand[1].type == UD_OP_CONST ) 241 cast = 1; 242 if ( u->operand[1].type == UD_NONE ) 243 cast = 1; 244 if ( ( u->operand[0].size != u->operand[1].size ) && u->operand[1].size ) 245 cast = 1; 246 } else if ( u->operand[ 0 ].type == UD_OP_JIMM ) { 247 if ( u->operand[ 0 ].size > 8 ) cast = 1; 248 } 249 gen_operand(u, &u->operand[0], cast); 250 } 251 /* operand 2 */ 252 if (u->operand[1].type != UD_NONE) { 253 int cast = 0; 254 mkasm(u, ", "); 255 if ( u->operand[1].type == UD_OP_MEM ) { 256 cast = u->c1; 257 258 if ( u->operand[0].type != UD_OP_REG ) 259 cast = 1; 260 if ( u->operand[0].size != u->operand[1].size && u->operand[1].size ) 261 cast = 1; 262 if ( u->operand[0].type == UD_OP_REG && 263 u->operand[0].base >= UD_R_ES && 264 u->operand[0].base <= UD_R_GS ) 265 cast = 0; 266 } 267 gen_operand(u, &u->operand[1], cast ); 268 } 269 270 /* operand 3 */ 271 if (u->operand[2].type != UD_NONE) { 272 mkasm(u, ", "); 273 gen_operand(u, &u->operand[2], u->c3); 274 } 275} 276 277#endif // USE(UDIS86) 278 279