1/* udis86 - libudis86/syn-att.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 16 : case 32 : 45 mkasm(u, "*"); break; 46 default: break; 47 } 48} 49 50/* ----------------------------------------------------------------------------- 51 * gen_operand() - Generates assembly output for each operand. 52 * ----------------------------------------------------------------------------- 53 */ 54static void 55gen_operand(struct ud* u, struct ud_operand* op) 56{ 57 switch(op->type) { 58 case UD_OP_REG: 59 mkasm(u, "%%%s", ud_reg_tab[op->base - UD_R_AL]); 60 break; 61 62 case UD_OP_MEM: 63 if (u->br_far) opr_cast(u, op); 64 if (u->pfx_seg) 65 mkasm(u, "%%%s:", ud_reg_tab[u->pfx_seg - UD_R_AL]); 66 if (op->offset == 8) { 67 if (op->lval.sbyte < 0) 68 mkasm(u, "-0x%x", (-op->lval.sbyte) & 0xff); 69 else mkasm(u, "0x%x", op->lval.sbyte); 70 } 71 else if (op->offset == 16) 72 mkasm(u, "0x%x", op->lval.uword); 73 else if (op->offset == 32) 74 mkasm(u, "0x%lx", (unsigned long)op->lval.udword); 75 else if (op->offset == 64) 76 mkasm(u, "0x" FMT64 "x", op->lval.uqword); 77 78 if (op->base) 79 mkasm(u, "(%%%s", ud_reg_tab[op->base - UD_R_AL]); 80 if (op->index) { 81 if (op->base) 82 mkasm(u, ","); 83 else mkasm(u, "("); 84 mkasm(u, "%%%s", ud_reg_tab[op->index - UD_R_AL]); 85 } 86 if (op->scale) 87 mkasm(u, ",%d", op->scale); 88 if (op->base || op->index) 89 mkasm(u, ")"); 90 break; 91 92 case UD_OP_IMM: { 93 int64_t imm = 0; 94 uint64_t sext_mask = 0xffffffffffffffffull; 95 unsigned sext_size = op->size; 96 97 switch (op->size) { 98 case 8: imm = op->lval.sbyte; break; 99 case 16: imm = op->lval.sword; break; 100 case 32: imm = op->lval.sdword; break; 101 case 64: imm = op->lval.sqword; break; 102 } 103 if ( P_SEXT( u->itab_entry->prefix ) ) { 104 sext_size = u->operand[ 0 ].size; 105 if ( u->mnemonic == UD_Ipush ) 106 /* push sign-extends to operand size */ 107 sext_size = u->opr_mode; 108 } 109 if ( sext_size < 64 ) 110 sext_mask = ( 1ull << sext_size ) - 1; 111 mkasm( u, "$0x" FMT64 "x", imm & sext_mask ); 112 113 break; 114 } 115 116 case UD_OP_JIMM: 117 switch (op->size) { 118 case 8: 119 mkasm(u, "0x" FMT64 "x", u->pc + op->lval.sbyte); 120 break; 121 case 16: 122 mkasm(u, "0x" FMT64 "x", (u->pc + op->lval.sword) & 0xffff ); 123 break; 124 case 32: 125 if (u->dis_mode == 32) 126 mkasm(u, "0x" FMT64 "x", (u->pc + op->lval.sdword) & 0xffffffff); 127 else 128 mkasm(u, "0x" FMT64 "x", u->pc + op->lval.sdword); 129 break; 130 default:break; 131 } 132 break; 133 134 case UD_OP_PTR: 135 switch (op->size) { 136 case 32: 137 mkasm(u, "$0x%x, $0x%x", op->lval.ptr.seg, 138 op->lval.ptr.off & 0xFFFF); 139 break; 140 case 48: 141 mkasm(u, "$0x%x, $0x%lx", op->lval.ptr.seg, 142 (unsigned long)op->lval.ptr.off); 143 break; 144 } 145 break; 146 147 default: return; 148 } 149} 150 151/* ============================================================================= 152 * translates to AT&T syntax 153 * ============================================================================= 154 */ 155extern void 156ud_translate_att(struct ud *u) 157{ 158 int size = 0; 159 160 /* check if P_OSO prefix is used */ 161 if (! P_OSO(u->itab_entry->prefix) && u->pfx_opr) { 162 switch (u->dis_mode) { 163 case 16: 164 mkasm(u, "o32 "); 165 break; 166 case 32: 167 case 64: 168 mkasm(u, "o16 "); 169 break; 170 } 171 } 172 173 /* check if P_ASO prefix was used */ 174 if (! P_ASO(u->itab_entry->prefix) && u->pfx_adr) { 175 switch (u->dis_mode) { 176 case 16: 177 mkasm(u, "a32 "); 178 break; 179 case 32: 180 mkasm(u, "a16 "); 181 break; 182 case 64: 183 mkasm(u, "a32 "); 184 break; 185 } 186 } 187 188 if (u->pfx_lock) 189 mkasm(u, "lock "); 190 if (u->pfx_rep) 191 mkasm(u, "rep "); 192 if (u->pfx_repne) 193 mkasm(u, "repne "); 194 195 /* special instructions */ 196 switch (u->mnemonic) { 197 case UD_Iretf: 198 mkasm(u, "lret "); 199 break; 200 case UD_Idb: 201 mkasm(u, ".byte 0x%x", u->operand[0].lval.ubyte); 202 return; 203 case UD_Ijmp: 204 case UD_Icall: 205 if (u->br_far) mkasm(u, "l"); 206 mkasm(u, "%s", ud_lookup_mnemonic(u->mnemonic)); 207 break; 208 case UD_Ibound: 209 case UD_Ienter: 210 if (u->operand[0].type != UD_NONE) 211 gen_operand(u, &u->operand[0]); 212 if (u->operand[1].type != UD_NONE) { 213 mkasm(u, ","); 214 gen_operand(u, &u->operand[1]); 215 } 216 return; 217 default: 218 mkasm(u, "%s", ud_lookup_mnemonic(u->mnemonic)); 219 } 220 221 if (u->c1) 222 size = u->operand[0].size; 223 else if (u->c2) 224 size = u->operand[1].size; 225 else if (u->c3) 226 size = u->operand[2].size; 227 228 if (size == 8) 229 mkasm(u, "b"); 230 else if (size == 16) 231 mkasm(u, "w"); 232 else if (size == 64) 233 mkasm(u, "q"); 234 235 mkasm(u, " "); 236 237 if (u->operand[2].type != UD_NONE) { 238 gen_operand(u, &u->operand[2]); 239 mkasm(u, ", "); 240 } 241 242 if (u->operand[1].type != UD_NONE) { 243 gen_operand(u, &u->operand[1]); 244 mkasm(u, ", "); 245 } 246 247 if (u->operand[0].type != UD_NONE) 248 gen_operand(u, &u->operand[0]); 249} 250 251#endif // USE(UDIS86) 252 253