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 "types.h" 27#include "extern.h" 28#include "decode.h" 29#include "itab.h" 30#include "syn.h" 31#include "udint.h" 32 33/* ----------------------------------------------------------------------------- 34 * opr_cast() - Prints an operand cast. 35 * ----------------------------------------------------------------------------- 36 */ 37static void 38opr_cast(struct ud* u, struct ud_operand* op) 39{ 40 switch(op->size) { 41 case 16 : case 32 : 42 ud_asmprintf(u, "*"); break; 43 default: break; 44 } 45} 46 47/* ----------------------------------------------------------------------------- 48 * gen_operand() - Generates assembly output for each operand. 49 * ----------------------------------------------------------------------------- 50 */ 51static void 52gen_operand(struct ud* u, struct ud_operand* op) 53{ 54 switch(op->type) { 55 case UD_OP_CONST: 56 ud_asmprintf(u, "$0x%x", op->lval.udword); 57 break; 58 59 case UD_OP_REG: 60 ud_asmprintf(u, "%%%s", ud_reg_tab[op->base - UD_R_AL]); 61 break; 62 63 case UD_OP_MEM: 64 if (u->br_far) { 65 opr_cast(u, op); 66 } 67 if (u->pfx_seg) { 68 ud_asmprintf(u, "%%%s:", ud_reg_tab[u->pfx_seg - UD_R_AL]); 69 } 70 if (op->offset != 0) { 71 ud_syn_print_mem_disp(u, op, 0); 72 } 73 if (op->base) { 74 ud_asmprintf(u, "(%%%s", ud_reg_tab[op->base - UD_R_AL]); 75 } 76 if (op->index) { 77 if (op->base) { 78 ud_asmprintf(u, ","); 79 } else { 80 ud_asmprintf(u, "("); 81 } 82 ud_asmprintf(u, "%%%s", ud_reg_tab[op->index - UD_R_AL]); 83 } 84 if (op->scale) { 85 ud_asmprintf(u, ",%d", op->scale); 86 } 87 if (op->base || op->index) { 88 ud_asmprintf(u, ")"); 89 } 90 break; 91 92 case UD_OP_IMM: 93 ud_asmprintf(u, "$"); 94 ud_syn_print_imm(u, op); 95 break; 96 97 case UD_OP_JIMM: 98 ud_syn_print_addr(u, ud_syn_rel_target(u, op)); 99 break; 100 101 case UD_OP_PTR: 102 switch (op->size) { 103 case 32: 104 ud_asmprintf(u, "$0x%x, $0x%x", op->lval.ptr.seg, 105 op->lval.ptr.off & 0xFFFF); 106 break; 107 case 48: 108 ud_asmprintf(u, "$0x%x, $0x%x", op->lval.ptr.seg, 109 op->lval.ptr.off); 110 break; 111 } 112 break; 113 114 default: return; 115 } 116} 117 118/* ============================================================================= 119 * translates to AT&T syntax 120 * ============================================================================= 121 */ 122extern void 123ud_translate_att(struct ud *u) 124{ 125 int size = 0; 126 int star = 0; 127 128 /* check if P_OSO prefix is used */ 129 if (! P_OSO(u->itab_entry->prefix) && u->pfx_opr) { 130 switch (u->dis_mode) { 131 case 16: 132 ud_asmprintf(u, "o32 "); 133 break; 134 case 32: 135 case 64: 136 ud_asmprintf(u, "o16 "); 137 break; 138 } 139 } 140 141 /* check if P_ASO prefix was used */ 142 if (! P_ASO(u->itab_entry->prefix) && u->pfx_adr) { 143 switch (u->dis_mode) { 144 case 16: 145 ud_asmprintf(u, "a32 "); 146 break; 147 case 32: 148 ud_asmprintf(u, "a16 "); 149 break; 150 case 64: 151 ud_asmprintf(u, "a32 "); 152 break; 153 } 154 } 155 156 if (u->pfx_lock) 157 ud_asmprintf(u, "lock "); 158 if (u->pfx_rep) { 159 ud_asmprintf(u, "rep "); 160 } else if (u->pfx_repe) { 161 ud_asmprintf(u, "repe "); 162 } else if (u->pfx_repne) { 163 ud_asmprintf(u, "repne "); 164 } 165 166 /* special instructions */ 167 switch (u->mnemonic) { 168 case UD_Iretf: 169 ud_asmprintf(u, "lret "); 170 break; 171 case UD_Idb: 172 ud_asmprintf(u, ".byte 0x%x", u->operand[0].lval.ubyte); 173 return; 174 case UD_Ijmp: 175 case UD_Icall: 176 if (u->br_far) ud_asmprintf(u, "l"); 177 if (u->operand[0].type == UD_OP_REG) { 178 star = 1; 179 } 180 ud_asmprintf(u, "%s", ud_lookup_mnemonic(u->mnemonic)); 181 break; 182 case UD_Ibound: 183 case UD_Ienter: 184 if (u->operand[0].type != UD_NONE) 185 gen_operand(u, &u->operand[0]); 186 if (u->operand[1].type != UD_NONE) { 187 ud_asmprintf(u, ","); 188 gen_operand(u, &u->operand[1]); 189 } 190 return; 191 default: 192 ud_asmprintf(u, "%s", ud_lookup_mnemonic(u->mnemonic)); 193 } 194 195 if (size == 8) { 196 ud_asmprintf(u, "b"); 197 } else if (size == 16) { 198 ud_asmprintf(u, "w"); 199 } else if (size == 64) { 200 ud_asmprintf(u, "q"); 201 } 202 203 if (star) { 204 ud_asmprintf(u, " *"); 205 } else { 206 ud_asmprintf(u, " "); 207 } 208 209 if (u->operand[3].type != UD_NONE) { 210 gen_operand(u, &u->operand[3]); 211 ud_asmprintf(u, ", "); 212 } 213 if (u->operand[2].type != UD_NONE) { 214 gen_operand(u, &u->operand[2]); 215 ud_asmprintf(u, ", "); 216 } 217 if (u->operand[1].type != UD_NONE) { 218 gen_operand(u, &u->operand[1]); 219 ud_asmprintf(u, ", "); 220 } 221 if (u->operand[0].type != UD_NONE) { 222 gen_operand(u, &u->operand[0]); 223 } 224} 225 226/* 227vim: set ts=2 sw=2 expandtab 228*/ 229