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