Home | History | Annotate | Download | only in libyasm
      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