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