1 /* 2 * Mnemonic instruction bytecode 3 * 4 * Copyright (C) 2005-2007 Peter Johnson 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS'' 16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE 19 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 * POSSIBILITY OF SUCH DAMAGE. 26 */ 27 #include "util.h" 28 29 #include "libyasm-stdint.h" 30 #include "coretype.h" 31 32 #include "errwarn.h" 33 #include "expr.h" 34 #include "value.h" 35 36 #include "bytecode.h" 37 #include "insn.h" 38 #include "arch.h" 39 40 41 void 42 yasm_ea_set_segreg(yasm_effaddr *ea, uintptr_t segreg) 43 { 44 if (!ea) 45 return; 46 47 if (segreg != 0 && ea->segreg != 0) 48 yasm_warn_set(YASM_WARN_GENERAL, 49 N_("multiple segment overrides, using leftmost")); 50 51 ea->segreg = segreg; 52 } 53 54 yasm_insn_operand * 55 yasm_operand_create_reg(uintptr_t reg) 56 { 57 yasm_insn_operand *retval = yasm_xmalloc(sizeof(yasm_insn_operand)); 58 59 retval->type = YASM_INSN__OPERAND_REG; 60 retval->data.reg = reg; 61 retval->seg = 0; 62 retval->targetmod = 0; 63 retval->size = 0; 64 retval->deref = 0; 65 retval->strict = 0; 66 67 return retval; 68 } 69 70 yasm_insn_operand * 71 yasm_operand_create_segreg(uintptr_t segreg) 72 { 73 yasm_insn_operand *retval = yasm_xmalloc(sizeof(yasm_insn_operand)); 74 75 retval->type = YASM_INSN__OPERAND_SEGREG; 76 retval->data.reg = segreg; 77 retval->seg = 0; 78 retval->targetmod = 0; 79 retval->size = 0; 80 retval->deref = 0; 81 retval->strict = 0; 82 83 return retval; 84 } 85 86 yasm_insn_operand * 87 yasm_operand_create_mem(/*@only@*/ yasm_effaddr *ea) 88 { 89 yasm_insn_operand *retval = yasm_xmalloc(sizeof(yasm_insn_operand)); 90 91 retval->type = YASM_INSN__OPERAND_MEMORY; 92 retval->data.ea = ea; 93 retval->seg = 0; 94 retval->targetmod = 0; 95 retval->size = 0; 96 retval->deref = 0; 97 retval->strict = 0; 98 retval->size = ea->data_len * 8; 99 100 return retval; 101 } 102 103 yasm_insn_operand * 104 yasm_operand_create_imm(/*@only@*/ yasm_expr *val) 105 { 106 yasm_insn_operand *retval; 107 const uintptr_t *reg; 108 109 reg = yasm_expr_get_reg(&val, 0); 110 if (reg) { 111 retval = yasm_operand_create_reg(*reg); 112 yasm_expr_destroy(val); 113 } else { 114 retval = yasm_xmalloc(sizeof(yasm_insn_operand)); 115 retval->type = YASM_INSN__OPERAND_IMM; 116 retval->data.val = val; 117 retval->seg = 0; 118 retval->targetmod = 0; 119 retval->size = 0; 120 retval->deref = 0; 121 retval->strict = 0; 122 } 123 124 return retval; 125 } 126 127 yasm_insn_operand * 128 yasm_insn_ops_append(yasm_insn *insn, yasm_insn_operand *op) 129 { 130 if (op) { 131 insn->num_operands++; 132 STAILQ_INSERT_TAIL(&insn->operands, op, link); 133 return op; 134 } 135 return (yasm_insn_operand *)NULL; 136 } 137 138 void 139 yasm_insn_add_prefix(yasm_insn *insn, uintptr_t prefix) 140 { 141 insn->prefixes = 142 yasm_xrealloc(insn->prefixes, 143 (insn->num_prefixes+1)*sizeof(uintptr_t)); 144 insn->prefixes[insn->num_prefixes] = prefix; 145 insn->num_prefixes++; 146 } 147 148 void 149 yasm_insn_add_seg_prefix(yasm_insn *insn, uintptr_t segreg) 150 { 151 insn->segregs = 152 yasm_xrealloc(insn->segregs, (insn->num_segregs+1)*sizeof(uintptr_t)); 153 insn->segregs[insn->num_segregs] = segreg; 154 insn->num_segregs++; 155 } 156 157 void 158 yasm_insn_initialize(yasm_insn *insn) 159 { 160 STAILQ_INIT(&insn->operands); 161 162 insn->prefixes = NULL; 163 insn->segregs = NULL; 164 165 insn->num_operands = 0; 166 insn->num_prefixes = 0; 167 insn->num_segregs = 0; 168 } 169 170 void 171 yasm_insn_delete(yasm_insn *insn, 172 void (*ea_destroy) (/*@only@*/ yasm_effaddr *)) 173 { 174 if (insn->num_operands > 0) { 175 yasm_insn_operand *cur, *next; 176 177 cur = STAILQ_FIRST(&insn->operands); 178 while (cur) { 179 next = STAILQ_NEXT(cur, link); 180 switch (cur->type) { 181 case YASM_INSN__OPERAND_MEMORY: 182 ea_destroy(cur->data.ea); 183 break; 184 case YASM_INSN__OPERAND_IMM: 185 yasm_expr_destroy(cur->data.val); 186 break; 187 default: 188 break; 189 } 190 yasm_xfree(cur); 191 cur = next; 192 } 193 } 194 if (insn->num_prefixes > 0) 195 yasm_xfree(insn->prefixes); 196 if (insn->num_segregs > 0) 197 yasm_xfree(insn->segregs); 198 } 199 200 void 201 yasm_insn_print(const yasm_insn *insn, FILE *f, int indent_level) 202 { 203 const yasm_insn_operand *op; 204 205 STAILQ_FOREACH (op, &insn->operands, link) { 206 switch (op->type) { 207 case YASM_INSN__OPERAND_REG: 208 fprintf(f, "%*sReg=", indent_level, ""); 209 /*yasm_arch_reg_print(arch, op->data.reg, f);*/ 210 fprintf(f, "\n"); 211 break; 212 case YASM_INSN__OPERAND_SEGREG: 213 fprintf(f, "%*sSegReg=", indent_level, ""); 214 /*yasm_arch_segreg_print(arch, op->data.reg, f);*/ 215 fprintf(f, "\n"); 216 break; 217 case YASM_INSN__OPERAND_MEMORY: 218 fprintf(f, "%*sMemory=\n", indent_level, ""); 219 /*yasm_arch_ea_print(arch, op->data.ea, f, indent_level);*/ 220 break; 221 case YASM_INSN__OPERAND_IMM: 222 fprintf(f, "%*sImm=", indent_level, ""); 223 yasm_expr_print(op->data.val, f); 224 fprintf(f, "\n"); 225 break; 226 } 227 fprintf(f, "%*sTargetMod=%lx\n", indent_level+1, "", 228 (unsigned long)op->targetmod); 229 fprintf(f, "%*sSize=%u\n", indent_level+1, "", op->size); 230 fprintf(f, "%*sDeref=%d, Strict=%d\n", indent_level+1, "", 231 (int)op->deref, (int)op->strict); 232 } 233 } 234 235 void 236 yasm_insn_finalize(yasm_insn *insn) 237 { 238 unsigned int i; 239 yasm_insn_operand *op; 240 yasm_error_class eclass; 241 char *str, *xrefstr; 242 unsigned long xrefline; 243 244 /* Simplify the operands' expressions first. */ 245 for (i = 0, op = yasm_insn_ops_first(insn); 246 op && i<insn->num_operands; op = yasm_insn_op_next(op), i++) { 247 /* Check operand type */ 248 switch (op->type) { 249 case YASM_INSN__OPERAND_MEMORY: 250 /* Don't get over-ambitious here; some archs' memory expr 251 * parser are sensitive to the presence of *1, etc, so don't 252 * simplify reg*1 identities. 253 */ 254 if (op->data.ea) 255 op->data.ea->disp.abs = 256 yasm_expr__level_tree(op->data.ea->disp.abs, 1, 1, 0, 257 0, NULL, NULL); 258 if (yasm_error_occurred()) { 259 /* Add a pointer to where it was used to the error */ 260 yasm_error_fetch(&eclass, &str, &xrefline, &xrefstr); 261 if (xrefstr) { 262 yasm_error_set_xref(xrefline, "%s", xrefstr); 263 yasm_xfree(xrefstr); 264 } 265 if (str) { 266 yasm_error_set(eclass, "%s in memory expression", str); 267 yasm_xfree(str); 268 } 269 return; 270 } 271 break; 272 case YASM_INSN__OPERAND_IMM: 273 op->data.val = 274 yasm_expr__level_tree(op->data.val, 1, 1, 1, 0, NULL, 275 NULL); 276 if (yasm_error_occurred()) { 277 /* Add a pointer to where it was used to the error */ 278 yasm_error_fetch(&eclass, &str, &xrefline, &xrefstr); 279 if (xrefstr) { 280 yasm_error_set_xref(xrefline, "%s", xrefstr); 281 yasm_xfree(xrefstr); 282 } 283 if (str) { 284 yasm_error_set(eclass, "%s in immediate expression", 285 str); 286 yasm_xfree(str); 287 } 288 return; 289 } 290 break; 291 default: 292 break; 293 } 294 } 295 } 296