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