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