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  */
37 static void
opr_cast(struct ud * u,struct ud_operand * op)38 opr_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  */
51 static void
gen_operand(struct ud * u,struct ud_operand * op)52 gen_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  */
122 extern void
ud_translate_att(struct ud * u)123 ud_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 /*
227 vim: set ts=2 sw=2 expandtab
228 */
229