1/*
2 * x86 bytecode utility functions
3 *
4 *  Copyright (C) 2001-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.h>
30
31#include "x86arch.h"
32
33
34/* Bytecode callback function prototypes */
35
36static void x86_bc_insn_destroy(void *contents);
37static void x86_bc_insn_print(const void *contents, FILE *f,
38                              int indent_level);
39static int x86_bc_insn_calc_len(yasm_bytecode *bc,
40                                yasm_bc_add_span_func add_span,
41                                void *add_span_data);
42static int x86_bc_insn_expand(yasm_bytecode *bc, int span, long old_val,
43                              long new_val, /*@out@*/ long *neg_thres,
44                              /*@out@*/ long *pos_thres);
45static int x86_bc_insn_tobytes(yasm_bytecode *bc, unsigned char **bufp,
46                               unsigned char *bufstart,
47                               void *d, yasm_output_value_func output_value,
48                               /*@null@*/ yasm_output_reloc_func output_reloc);
49
50static void x86_bc_jmp_destroy(void *contents);
51static void x86_bc_jmp_print(const void *contents, FILE *f, int indent_level);
52static int x86_bc_jmp_calc_len(yasm_bytecode *bc,
53                               yasm_bc_add_span_func add_span,
54                               void *add_span_data);
55static int x86_bc_jmp_expand(yasm_bytecode *bc, int span, long old_val,
56                             long new_val, /*@out@*/ long *neg_thres,
57                             /*@out@*/ long *pos_thres);
58static int x86_bc_jmp_tobytes(yasm_bytecode *bc, unsigned char **bufp,
59                              unsigned char *bufstart,
60                              void *d, yasm_output_value_func output_value,
61                              /*@null@*/ yasm_output_reloc_func output_reloc);
62
63static void x86_bc_jmpfar_destroy(void *contents);
64static void x86_bc_jmpfar_print(const void *contents, FILE *f,
65                                int indent_level);
66static int x86_bc_jmpfar_calc_len(yasm_bytecode *bc,
67                                  yasm_bc_add_span_func add_span,
68                                  void *add_span_data);
69static int x86_bc_jmpfar_tobytes
70    (yasm_bytecode *bc, unsigned char **bufp, unsigned char *bufstart, void *d,
71     yasm_output_value_func output_value,
72     /*@null@*/ yasm_output_reloc_func output_reloc);
73
74/* Bytecode callback structures */
75
76static const yasm_bytecode_callback x86_bc_callback_insn = {
77    x86_bc_insn_destroy,
78    x86_bc_insn_print,
79    yasm_bc_finalize_common,
80    NULL,
81    x86_bc_insn_calc_len,
82    x86_bc_insn_expand,
83    x86_bc_insn_tobytes,
84    0
85};
86
87static const yasm_bytecode_callback x86_bc_callback_jmp = {
88    x86_bc_jmp_destroy,
89    x86_bc_jmp_print,
90    yasm_bc_finalize_common,
91    NULL,
92    x86_bc_jmp_calc_len,
93    x86_bc_jmp_expand,
94    x86_bc_jmp_tobytes,
95    0
96};
97
98static const yasm_bytecode_callback x86_bc_callback_jmpfar = {
99    x86_bc_jmpfar_destroy,
100    x86_bc_jmpfar_print,
101    yasm_bc_finalize_common,
102    NULL,
103    x86_bc_jmpfar_calc_len,
104    yasm_bc_expand_common,
105    x86_bc_jmpfar_tobytes,
106    0
107};
108
109int
110yasm_x86__set_rex_from_reg(unsigned char *rex, unsigned char *low3,
111                           uintptr_t reg, unsigned int bits,
112                           x86_rex_bit_pos rexbit)
113{
114    *low3 = (unsigned char)(reg&7);
115
116    if (bits == 64) {
117        x86_expritem_reg_size size = (x86_expritem_reg_size)(reg & ~0xFUL);
118
119        if (size == X86_REG8X || (reg & 0xF) >= 8) {
120            /* Check to make sure we can set it */
121            if (*rex == 0xff) {
122                yasm_error_set(YASM_ERROR_TYPE,
123                    N_("cannot use A/B/C/DH with instruction needing REX"));
124                return 1;
125            }
126            *rex |= 0x40 | (((reg & 8) >> 3) << rexbit);
127        } else if (size == X86_REG8 && (reg & 7) >= 4) {
128            /* AH/BH/CH/DH, so no REX allowed */
129            if (*rex != 0 && *rex != 0xff) {
130                yasm_error_set(YASM_ERROR_TYPE,
131                    N_("cannot use A/B/C/DH with instruction needing REX"));
132                return 1;
133            }
134            *rex = 0xff;    /* Flag so we can NEVER set it (see above) */
135        }
136    }
137
138    return 0;
139}
140
141void
142yasm_x86__bc_transform_insn(yasm_bytecode *bc, x86_insn *insn)
143{
144    yasm_bc_transform(bc, &x86_bc_callback_insn, insn);
145}
146
147void
148yasm_x86__bc_transform_jmp(yasm_bytecode *bc, x86_jmp *jmp)
149{
150    yasm_bc_transform(bc, &x86_bc_callback_jmp, jmp);
151}
152
153void
154yasm_x86__bc_transform_jmpfar(yasm_bytecode *bc, x86_jmpfar *jmpfar)
155{
156    yasm_bc_transform(bc, &x86_bc_callback_jmpfar, jmpfar);
157}
158
159void
160yasm_x86__ea_init(x86_effaddr *x86_ea, unsigned int spare,
161                  yasm_bytecode *precbc)
162{
163    if (yasm_value_finalize(&x86_ea->ea.disp, precbc))
164        yasm_error_set(YASM_ERROR_TOO_COMPLEX,
165                       N_("effective address too complex"));
166    x86_ea->modrm &= 0xC7;                  /* zero spare/reg bits */
167    x86_ea->modrm |= (spare << 3) & 0x38;   /* plug in provided bits */
168}
169
170void
171yasm_x86__ea_set_disponly(x86_effaddr *x86_ea)
172{
173    x86_ea->valid_modrm = 0;
174    x86_ea->need_modrm = 0;
175    x86_ea->valid_sib = 0;
176    x86_ea->need_sib = 0;
177}
178
179static x86_effaddr *
180ea_create(void)
181{
182    x86_effaddr *x86_ea = yasm_xmalloc(sizeof(x86_effaddr));
183
184    yasm_value_initialize(&x86_ea->ea.disp, NULL, 0);
185    x86_ea->ea.need_nonzero_len = 0;
186    x86_ea->ea.need_disp = 0;
187    x86_ea->ea.nosplit = 0;
188    x86_ea->ea.strong = 0;
189    x86_ea->ea.segreg = 0;
190    x86_ea->ea.pc_rel = 0;
191    x86_ea->ea.not_pc_rel = 0;
192    x86_ea->ea.data_len = 0;
193    x86_ea->vsib_mode = 0;
194    x86_ea->modrm = 0;
195    x86_ea->valid_modrm = 0;
196    x86_ea->need_modrm = 0;
197    x86_ea->sib = 0;
198    x86_ea->valid_sib = 0;
199    x86_ea->need_sib = 0;
200
201    return x86_ea;
202}
203
204x86_effaddr *
205yasm_x86__ea_create_reg(x86_effaddr *x86_ea, unsigned long reg,
206                        unsigned char *rex, unsigned int bits)
207{
208    unsigned char rm;
209
210    if (yasm_x86__set_rex_from_reg(rex, &rm, reg, bits, X86_REX_B))
211        return NULL;
212
213    if (!x86_ea)
214        x86_ea = ea_create();
215    x86_ea->modrm = 0xC0 | rm;  /* Mod=11, R/M=Reg, Reg=0 */
216    x86_ea->valid_modrm = 1;
217    x86_ea->need_modrm = 1;
218
219    return x86_ea;
220}
221
222yasm_effaddr *
223yasm_x86__ea_create_expr(yasm_arch *arch, yasm_expr *e)
224{
225    yasm_arch_x86 *arch_x86 = (yasm_arch_x86 *)arch;
226    x86_effaddr *x86_ea;
227
228    x86_ea = ea_create();
229
230    if (arch_x86->parser == X86_PARSER_GAS) {
231        /* Need to change foo+rip into foo wrt rip (even in .intel_syntax mode).
232         * Note this assumes a particular ordering coming from the parser
233         * to work (it's not very smart)!
234         */
235        if (e->op == YASM_EXPR_ADD && e->terms[0].type == YASM_EXPR_REG
236            && e->terms[0].data.reg == X86_RIP) {
237            /* replace register with 0 */
238            e->terms[0].type = YASM_EXPR_INT;
239            e->terms[0].data.intn = yasm_intnum_create_uint(0);
240            /* build new wrt expression */
241            e = yasm_expr_create(YASM_EXPR_WRT, yasm_expr_expr(e),
242                                 yasm_expr_reg(X86_RIP), e->line);
243        }
244    }
245    yasm_value_initialize(&x86_ea->ea.disp, e, 0);
246    x86_ea->ea.need_disp = 1;
247    x86_ea->need_modrm = 1;
248    /* We won't know whether we need an SIB until we know more about expr and
249     * the BITS/address override setting.
250     */
251    x86_ea->need_sib = 0xff;
252
253    x86_ea->ea.data_len = 0;
254
255    return (yasm_effaddr *)x86_ea;
256}
257
258/*@-compmempass@*/
259x86_effaddr *
260yasm_x86__ea_create_imm(x86_effaddr *x86_ea, yasm_expr *imm,
261                        unsigned int im_len)
262{
263    if (!x86_ea)
264        x86_ea = ea_create();
265    yasm_value_initialize(&x86_ea->ea.disp, imm, im_len);
266    x86_ea->ea.need_disp = 1;
267
268    return x86_ea;
269}
270/*@=compmempass@*/
271
272void
273yasm_x86__bc_apply_prefixes(x86_common *common, unsigned char *rex,
274                            unsigned int def_opersize_64,
275                            unsigned int num_prefixes, uintptr_t *prefixes)
276{
277    unsigned int i;
278    int first = 1;
279
280    for (i=0; i<num_prefixes; i++) {
281        switch ((x86_parse_insn_prefix)(prefixes[i] & 0xff00)) {
282            case X86_LOCKREP:
283                if (common->lockrep_pre != 0)
284                    yasm_warn_set(YASM_WARN_GENERAL,
285                        N_("multiple LOCK or REP prefixes, using leftmost"));
286                common->lockrep_pre = (unsigned char)prefixes[i] & 0xff;
287                break;
288            case X86_ADDRSIZE:
289                common->addrsize = (unsigned char)prefixes[i] & 0xff;
290                break;
291            case X86_OPERSIZE:
292                common->opersize = (unsigned char)prefixes[i] & 0xff;
293                if (common->mode_bits == 64 && common->opersize == 64 &&
294                    def_opersize_64 != 64) {
295                    if (!rex)
296                        yasm_warn_set(YASM_WARN_GENERAL,
297                                      N_("ignoring REX prefix on jump"));
298                    else if (*rex == 0xff)
299                        yasm_warn_set(YASM_WARN_GENERAL,
300                            N_("REX prefix not allowed on this instruction, ignoring"));
301                    else
302                        *rex = 0x48;
303                }
304                break;
305            case X86_SEGREG:
306                /* This is a hack.. we should really be putting this in the
307                 * the effective address!
308                 */
309                common->lockrep_pre = (unsigned char)prefixes[i] & 0xff;
310                break;
311            case X86_REX:
312                if (!rex)
313                    yasm_warn_set(YASM_WARN_GENERAL,
314                                  N_("ignoring REX prefix on jump"));
315                else if (*rex == 0xff)
316                    yasm_warn_set(YASM_WARN_GENERAL,
317                        N_("REX prefix not allowed on this instruction, ignoring"));
318                else {
319                    if (*rex != 0) {
320                        if (first)
321                            yasm_warn_set(YASM_WARN_GENERAL,
322                                N_("overriding generated REX prefix"));
323                        else
324                            yasm_warn_set(YASM_WARN_GENERAL,
325                                N_("multiple REX prefixes, using leftmost"));
326                    }
327                    /* Here we assume that we can't get this prefix in non
328                     * 64 bit mode due to checks in parse_check_prefix().
329                     */
330                    common->mode_bits = 64;
331                    *rex = (unsigned char)prefixes[i] & 0xff;
332                }
333                first = 0;
334                break;
335        }
336    }
337}
338
339static void
340x86_bc_insn_destroy(void *contents)
341{
342    x86_insn *insn = (x86_insn *)contents;
343    if (insn->x86_ea)
344        yasm_x86__ea_destroy((yasm_effaddr *)insn->x86_ea);
345    if (insn->imm) {
346        yasm_value_delete(insn->imm);
347        yasm_xfree(insn->imm);
348    }
349    yasm_xfree(contents);
350}
351
352static void
353x86_bc_jmp_destroy(void *contents)
354{
355    x86_jmp *jmp = (x86_jmp *)contents;
356    yasm_value_delete(&jmp->target);
357    yasm_xfree(contents);
358}
359
360static void
361x86_bc_jmpfar_destroy(void *contents)
362{
363    x86_jmpfar *jmpfar = (x86_jmpfar *)contents;
364    yasm_value_delete(&jmpfar->segment);
365    yasm_value_delete(&jmpfar->offset);
366    yasm_xfree(contents);
367}
368
369void
370yasm_x86__ea_destroy(yasm_effaddr *ea)
371{
372    yasm_value_delete(&ea->disp);
373    yasm_xfree(ea);
374}
375
376void
377yasm_x86__ea_print(const yasm_effaddr *ea, FILE *f, int indent_level)
378{
379    const x86_effaddr *x86_ea = (const x86_effaddr *)ea;
380    fprintf(f, "%*sDisp:\n", indent_level, "");
381    yasm_value_print(&ea->disp, f, indent_level+1);
382    fprintf(f, "%*sNoSplit=%u\n", indent_level, "", (unsigned int)ea->nosplit);
383    fprintf(f, "%*sSegmentOv=%02x\n", indent_level, "",
384            (unsigned int)x86_ea->ea.segreg);
385    fprintf(f, "%*sVSIBMode=%u\n", indent_level, "",
386            (unsigned int)x86_ea->vsib_mode);
387    fprintf(f, "%*sModRM=%03o ValidRM=%u NeedRM=%u\n", indent_level, "",
388            (unsigned int)x86_ea->modrm, (unsigned int)x86_ea->valid_modrm,
389            (unsigned int)x86_ea->need_modrm);
390    fprintf(f, "%*sSIB=%03o ValidSIB=%u NeedSIB=%u\n", indent_level, "",
391            (unsigned int)x86_ea->sib, (unsigned int)x86_ea->valid_sib,
392            (unsigned int)x86_ea->need_sib);
393}
394
395static void
396x86_common_print(const x86_common *common, FILE *f, int indent_level)
397{
398    fprintf(f, "%*sAddrSize=%u OperSize=%u LockRepPre=%02x BITS=%u\n",
399            indent_level, "",
400            (unsigned int)common->addrsize,
401            (unsigned int)common->opersize,
402            (unsigned int)common->lockrep_pre,
403            (unsigned int)common->mode_bits);
404}
405
406static void
407x86_opcode_print(const x86_opcode *opcode, FILE *f, int indent_level)
408{
409    fprintf(f, "%*sOpcode: %02x %02x %02x OpLen=%u\n", indent_level, "",
410            (unsigned int)opcode->opcode[0],
411            (unsigned int)opcode->opcode[1],
412            (unsigned int)opcode->opcode[2],
413            (unsigned int)opcode->len);
414}
415
416static void
417x86_bc_insn_print(const void *contents, FILE *f, int indent_level)
418{
419    const x86_insn *insn = (const x86_insn *)contents;
420
421    fprintf(f, "%*s_Instruction_\n", indent_level, "");
422    fprintf(f, "%*sEffective Address:", indent_level, "");
423    if (insn->x86_ea) {
424        fprintf(f, "\n");
425        yasm_x86__ea_print((yasm_effaddr *)insn->x86_ea, f, indent_level+1);
426    } else
427        fprintf(f, " (nil)\n");
428    fprintf(f, "%*sImmediate Value:", indent_level, "");
429    if (!insn->imm)
430        fprintf(f, " (nil)\n");
431    else {
432        indent_level++;
433        fprintf(f, "\n");
434        yasm_value_print(insn->imm, f, indent_level);
435        indent_level--;
436    }
437    x86_opcode_print(&insn->opcode, f, indent_level);
438    x86_common_print(&insn->common, f, indent_level);
439    fprintf(f, "%*sSpPre=%02x REX=%03o PostOp=%u\n", indent_level, "",
440            (unsigned int)insn->special_prefix,
441            (unsigned int)insn->rex,
442            (unsigned int)insn->postop);
443}
444
445static void
446x86_bc_jmp_print(const void *contents, FILE *f, int indent_level)
447{
448    const x86_jmp *jmp = (const x86_jmp *)contents;
449
450    fprintf(f, "%*s_Jump_\n", indent_level, "");
451    fprintf(f, "%*sTarget:\n", indent_level, "");
452    yasm_value_print(&jmp->target, f, indent_level+1);
453    /* FIXME
454    fprintf(f, "%*sOrigin=\n", indent_level, "");
455    yasm_symrec_print(jmp->origin, f, indent_level+1);
456    */
457    fprintf(f, "\n%*sShort Form:\n", indent_level, "");
458    if (jmp->shortop.len == 0)
459        fprintf(f, "%*sNone\n", indent_level+1, "");
460    else
461        x86_opcode_print(&jmp->shortop, f, indent_level+1);
462    fprintf(f, "%*sNear Form:\n", indent_level, "");
463    if (jmp->nearop.len == 0)
464        fprintf(f, "%*sNone\n", indent_level+1, "");
465    else
466        x86_opcode_print(&jmp->nearop, f, indent_level+1);
467    fprintf(f, "%*sOpSel=", indent_level, "");
468    switch (jmp->op_sel) {
469        case JMP_NONE:
470            fprintf(f, "None");
471            break;
472        case JMP_SHORT:
473            fprintf(f, "Short");
474            break;
475        case JMP_NEAR:
476            fprintf(f, "Near");
477            break;
478        case JMP_SHORT_FORCED:
479            fprintf(f, "Forced Short");
480            break;
481        case JMP_NEAR_FORCED:
482            fprintf(f, "Forced Near");
483            break;
484        default:
485            fprintf(f, "UNKNOWN!!");
486            break;
487    }
488    x86_common_print(&jmp->common, f, indent_level);
489}
490
491static void
492x86_bc_jmpfar_print(const void *contents, FILE *f, int indent_level)
493{
494    const x86_jmpfar *jmpfar = (const x86_jmpfar *)contents;
495
496    fprintf(f, "%*s_Far_Jump_\n", indent_level, "");
497    fprintf(f, "%*sSegment:\n", indent_level, "");
498    yasm_value_print(&jmpfar->segment, f, indent_level+1);
499    fprintf(f, "%*sOffset:\n", indent_level, "");
500    yasm_value_print(&jmpfar->offset, f, indent_level+1);
501    x86_opcode_print(&jmpfar->opcode, f, indent_level);
502    x86_common_print(&jmpfar->common, f, indent_level);
503}
504
505static unsigned int
506x86_common_calc_len(const x86_common *common)
507{
508    unsigned int len = 0;
509
510    if (common->addrsize != 0 && common->addrsize != common->mode_bits)
511        len++;
512    if (common->opersize != 0 &&
513        ((common->mode_bits != 64 && common->opersize != common->mode_bits) ||
514         (common->mode_bits == 64 && common->opersize == 16)))
515        len++;
516    if (common->lockrep_pre != 0)
517        len++;
518
519    return len;
520}
521
522static int
523x86_bc_insn_calc_len(yasm_bytecode *bc, yasm_bc_add_span_func add_span,
524                     void *add_span_data)
525{
526    x86_insn *insn = (x86_insn *)bc->contents;
527    x86_effaddr *x86_ea = insn->x86_ea;
528    yasm_value *imm = insn->imm;
529
530    if (x86_ea) {
531        /* Check validity of effective address and calc R/M bits of
532         * Mod/RM byte and SIB byte.  We won't know the Mod field
533         * of the Mod/RM byte until we know more about the
534         * displacement.
535         */
536        if (yasm_x86__expr_checkea(x86_ea, &insn->common.addrsize,
537                insn->common.mode_bits, insn->postop == X86_POSTOP_ADDRESS16,
538                &insn->rex, bc))
539            /* failed, don't bother checking rest of insn */
540            return -1;
541
542        if (x86_ea->ea.disp.size == 0 && x86_ea->ea.need_nonzero_len) {
543            /* Handle unknown case, default to byte-sized and set as
544             * critical expression.
545             */
546            x86_ea->ea.disp.size = 8;
547            add_span(add_span_data, bc, 1, &x86_ea->ea.disp, -128, 127);
548        }
549        bc->len += x86_ea->ea.disp.size/8;
550
551        /* Handle address16 postop case */
552        if (insn->postop == X86_POSTOP_ADDRESS16)
553            insn->common.addrsize = 0;
554
555        /* Compute length of ea and add to total */
556        bc->len += x86_ea->need_modrm + (x86_ea->need_sib ? 1:0);
557        bc->len += (x86_ea->ea.segreg != 0) ? 1 : 0;
558    }
559
560    if (imm) {
561        unsigned int immlen = imm->size;
562
563        /* TODO: check imm->len vs. sized len from expr? */
564
565        /* Handle signext_imm8 postop special-casing */
566        if (insn->postop == X86_POSTOP_SIGNEXT_IMM8) {
567            /*@null@*/ /*@only@*/ yasm_intnum *num;
568            num = yasm_value_get_intnum(imm, NULL, 0);
569
570            if (!num) {
571                /* Unknown; default to byte form and set as critical
572                 * expression.
573                 */
574                immlen = 8;
575                add_span(add_span_data, bc, 2, imm, -128, 127);
576            } else {
577                if (yasm_intnum_in_range(num, -128, 127)) {
578                    /* We can use the sign-extended byte form: shorten
579                     * the immediate length to 1 and make the byte form
580                     * permanent.
581                     */
582                    imm->size = 8;
583                    imm->sign = 1;
584                    immlen = 8;
585                } else {
586                    /* We can't.  Copy over the word-sized opcode. */
587                    insn->opcode.opcode[0] =
588                        insn->opcode.opcode[insn->opcode.len];
589                    insn->opcode.len = 1;
590                }
591                insn->postop = X86_POSTOP_NONE;
592                yasm_intnum_destroy(num);
593            }
594        }
595
596        bc->len += immlen/8;
597    }
598
599    /* VEX and XOP prefixes never have REX (it's embedded in the opcode).
600     * For VEX, we can come into this function with the three byte form,
601     * so we need to see if we can optimize to the two byte form.
602     * We can't do it earlier, as we don't know all of the REX byte until now.
603     */
604    if (insn->special_prefix == 0xC4) {
605        /* See if we can shorten the VEX prefix to its two byte form.
606         * In order to do this, REX.X, REX.B, and REX.W/VEX.W must all be 0,
607         * and the VEX mmmmm field must be 1.
608         */
609        if ((insn->opcode.opcode[0] & 0x1F) == 1 &&
610            (insn->opcode.opcode[1] & 0x80) == 0 &&
611            (insn->rex == 0xff || (insn->rex & 0x0B) == 0)) {
612            insn->opcode.opcode[0] = insn->opcode.opcode[1];
613            insn->opcode.opcode[1] = insn->opcode.opcode[2];
614            insn->opcode.opcode[2] = 0; /* sanity */
615            insn->opcode.len = 2;
616            insn->special_prefix = 0xC5;    /* mark as two-byte VEX */
617        }
618    } else if (insn->rex != 0xff && insn->rex != 0 &&
619               insn->special_prefix != 0xC5 && insn->special_prefix != 0x8F)
620        bc->len++;
621
622    bc->len += insn->opcode.len;
623    bc->len += x86_common_calc_len(&insn->common);
624    bc->len += (insn->special_prefix != 0) ? 1:0;
625    return 0;
626}
627
628static int
629x86_bc_insn_expand(yasm_bytecode *bc, int span, long old_val, long new_val,
630                   /*@out@*/ long *neg_thres, /*@out@*/ long *pos_thres)
631{
632    x86_insn *insn = (x86_insn *)bc->contents;
633    x86_effaddr *x86_ea = insn->x86_ea;
634    yasm_effaddr *ea = &x86_ea->ea;
635    yasm_value *imm = insn->imm;
636
637    if (ea && span == 1) {
638        /* Change displacement length into word-sized */
639        if (ea->disp.size == 8) {
640            ea->disp.size = (insn->common.addrsize == 16) ? 16 : 32;
641            x86_ea->modrm &= ~0300;
642            x86_ea->modrm |= 0200;
643            bc->len--;
644            bc->len += ea->disp.size/8;
645        }
646    }
647
648    if (imm && span == 2) {
649        if (insn->postop == X86_POSTOP_SIGNEXT_IMM8) {
650            /* Update bc->len for new opcode and immediate size */
651            bc->len -= insn->opcode.len;
652            bc->len += imm->size/8;
653
654            /* Change to the word-sized opcode */
655            insn->opcode.opcode[0] = insn->opcode.opcode[insn->opcode.len];
656            insn->opcode.len = 1;
657            insn->postop = X86_POSTOP_NONE;
658        }
659    }
660
661    return 0;
662}
663
664static int
665x86_bc_jmp_calc_len(yasm_bytecode *bc, yasm_bc_add_span_func add_span,
666                    void *add_span_data)
667{
668    x86_jmp *jmp = (x86_jmp *)bc->contents;
669    yasm_bytecode *target_prevbc;
670    unsigned char opersize;
671
672    /* As opersize may be 0, figure out its "real" value. */
673    opersize = (jmp->common.opersize == 0) ?
674        jmp->common.mode_bits : jmp->common.opersize;
675
676    bc->len += x86_common_calc_len(&jmp->common);
677
678    if (jmp->op_sel == JMP_NEAR_FORCED || jmp->shortop.len == 0) {
679        if (jmp->nearop.len == 0) {
680            yasm_error_set(YASM_ERROR_TYPE, N_("near jump does not exist"));
681            return -1;
682        }
683
684        /* Near jump, no spans needed */
685        if (jmp->shortop.len == 0)
686            jmp->op_sel = JMP_NEAR;
687        bc->len += jmp->nearop.len;
688        bc->len += (opersize == 16) ? 2 : 4;
689        return 0;
690    }
691
692    if (jmp->op_sel == JMP_SHORT_FORCED || jmp->nearop.len == 0) {
693        if (jmp->shortop.len == 0) {
694            yasm_error_set(YASM_ERROR_TYPE, N_("short jump does not exist"));
695            return -1;
696        }
697
698        /* We want to be sure to error if we exceed short length, so
699         * put it in as a dependent expression (falling through).
700         */
701    }
702
703    if (jmp->target.rel
704        && (!yasm_symrec_get_label(jmp->target.rel, &target_prevbc)
705            || target_prevbc->section != bc->section)) {
706        /* External or out of segment, so we can't check distance.
707         * Allowing short jumps depends on the objfmt supporting
708         * 8-bit relocs.  While most don't, some might, so allow it here.
709         * Otherwise default to word-sized.
710         * The objfmt will error if not supported.
711         */
712        if (jmp->op_sel == JMP_SHORT_FORCED || jmp->nearop.len == 0) {
713            if (jmp->op_sel == JMP_NONE)
714                jmp->op_sel = JMP_SHORT;
715            bc->len += jmp->shortop.len + 1;
716        } else {
717            jmp->op_sel = JMP_NEAR;
718            bc->len += jmp->nearop.len;
719            bc->len += (opersize == 16) ? 2 : 4;
720        }
721        return 0;
722    }
723
724    /* Default to short jump and generate span */
725    if (jmp->op_sel == JMP_NONE)
726        jmp->op_sel = JMP_SHORT;
727    bc->len += jmp->shortop.len + 1;
728    add_span(add_span_data, bc, 1, &jmp->target, -128+(long)bc->len,
729             127+(long)bc->len);
730    return 0;
731}
732
733static int
734x86_bc_jmp_expand(yasm_bytecode *bc, int span, long old_val, long new_val,
735                  /*@out@*/ long *neg_thres, /*@out@*/ long *pos_thres)
736{
737    x86_jmp *jmp = (x86_jmp *)bc->contents;
738    unsigned char opersize;
739
740    if (span != 1)
741        yasm_internal_error(N_("unrecognized span id"));
742
743    /* As opersize may be 0, figure out its "real" value. */
744    opersize = (jmp->common.opersize == 0) ?
745        jmp->common.mode_bits : jmp->common.opersize;
746
747    if (jmp->op_sel == JMP_SHORT_FORCED || jmp->nearop.len == 0) {
748        yasm_error_set(YASM_ERROR_VALUE, N_("short jump out of range"));
749        return -1;
750    }
751
752    if (jmp->op_sel == JMP_NEAR)
753        yasm_internal_error(N_("trying to expand an already-near jump"));
754
755    /* Upgrade to a near jump */
756    jmp->op_sel = JMP_NEAR;
757    bc->len -= jmp->shortop.len + 1;
758    bc->len += jmp->nearop.len;
759    bc->len += (opersize == 16) ? 2 : 4;
760
761    return 0;
762}
763
764static int
765x86_bc_jmpfar_calc_len(yasm_bytecode *bc, yasm_bc_add_span_func add_span,
766                       void *add_span_data)
767{
768    x86_jmpfar *jmpfar = (x86_jmpfar *)bc->contents;
769    unsigned char opersize;
770
771    opersize = (jmpfar->common.opersize == 0) ?
772        jmpfar->common.mode_bits : jmpfar->common.opersize;
773
774    bc->len += jmpfar->opcode.len;
775    bc->len += 2;       /* segment */
776    bc->len += (opersize == 16) ? 2 : 4;
777    bc->len += x86_common_calc_len(&jmpfar->common);
778
779    return 0;
780}
781
782static void
783x86_common_tobytes(const x86_common *common, unsigned char **bufp,
784                   unsigned int segreg)
785{
786    if (segreg != 0)
787        YASM_WRITE_8(*bufp, (unsigned char)segreg);
788    if (common->addrsize != 0 && common->addrsize != common->mode_bits)
789        YASM_WRITE_8(*bufp, 0x67);
790    if (common->opersize != 0 &&
791        ((common->mode_bits != 64 && common->opersize != common->mode_bits) ||
792         (common->mode_bits == 64 && common->opersize == 16)))
793        YASM_WRITE_8(*bufp, 0x66);
794    if (common->lockrep_pre != 0)
795        YASM_WRITE_8(*bufp, common->lockrep_pre);
796}
797
798static void
799x86_opcode_tobytes(const x86_opcode *opcode, unsigned char **bufp)
800{
801    unsigned int i;
802    for (i=0; i<opcode->len; i++)
803        YASM_WRITE_8(*bufp, opcode->opcode[i]);
804}
805
806static int
807x86_bc_insn_tobytes(yasm_bytecode *bc, unsigned char **bufp,
808                    unsigned char *bufstart, void *d,
809                    yasm_output_value_func output_value,
810                    /*@unused@*/ yasm_output_reloc_func output_reloc)
811{
812    x86_insn *insn = (x86_insn *)bc->contents;
813    /*@null@*/ x86_effaddr *x86_ea = (x86_effaddr *)insn->x86_ea;
814    yasm_value *imm = insn->imm;
815
816    /* Prefixes */
817    x86_common_tobytes(&insn->common, bufp,
818                       x86_ea ? (unsigned int)(x86_ea->ea.segreg>>8) : 0);
819    if (insn->special_prefix != 0)
820        YASM_WRITE_8(*bufp, insn->special_prefix);
821    if (insn->special_prefix == 0xC4 || insn->special_prefix == 0x8F) {
822        /* 3-byte VEX/XOP; merge in 1s complement of REX.R, REX.X, REX.B */
823        insn->opcode.opcode[0] &= 0x1F;
824        if (insn->rex != 0xff)
825            insn->opcode.opcode[0] |= ((~insn->rex) & 0x07) << 5;
826        /* merge REX.W via ORing; there should never be a case in which REX.W
827         * is important when VEX.W is already set by the instruction.
828         */
829        if (insn->rex != 0xff && (insn->rex & 0x8) != 0)
830            insn->opcode.opcode[1] |= 0x80;
831    } else if (insn->special_prefix == 0xC5) {
832        /* 2-byte VEX; merge in 1s complement of REX.R */
833        insn->opcode.opcode[0] &= 0x7F;
834        if (insn->rex != 0xff && (insn->rex & 0x4) == 0)
835            insn->opcode.opcode[0] |= 0x80;
836        /* No other REX bits should be set */
837        if (insn->rex != 0xff && (insn->rex & 0xB) != 0)
838            yasm_internal_error(N_("x86: REX.WXB set, but 2-byte VEX"));
839    } else if (insn->rex != 0xff && insn->rex != 0) {
840        if (insn->common.mode_bits != 64)
841            yasm_internal_error(N_("x86: got a REX prefix in non-64-bit mode"));
842        YASM_WRITE_8(*bufp, insn->rex);
843    }
844
845    /* Opcode */
846    x86_opcode_tobytes(&insn->opcode, bufp);
847
848    /* Effective address: ModR/M (if required), SIB (if required), and
849     * displacement (if required).
850     */
851    if (x86_ea) {
852        if (x86_ea->need_modrm) {
853            if (!x86_ea->valid_modrm)
854                yasm_internal_error(N_("invalid Mod/RM in x86 tobytes_insn"));
855            YASM_WRITE_8(*bufp, x86_ea->modrm);
856        }
857
858        if (x86_ea->need_sib) {
859            if (!x86_ea->valid_sib)
860                yasm_internal_error(N_("invalid SIB in x86 tobytes_insn"));
861            YASM_WRITE_8(*bufp, x86_ea->sib);
862        }
863
864        if (x86_ea->ea.need_disp) {
865            unsigned int disp_len = x86_ea->ea.disp.size/8;
866
867            if (x86_ea->ea.disp.ip_rel) {
868                /* Adjust relative displacement to end of bytecode */
869                /*@only@*/ yasm_intnum *delta;
870                delta = yasm_intnum_create_int(-(long)bc->len);
871                if (!x86_ea->ea.disp.abs)
872                    x86_ea->ea.disp.abs =
873                        yasm_expr_create_ident(yasm_expr_int(delta), bc->line);
874                else
875                    x86_ea->ea.disp.abs =
876                        yasm_expr_create(YASM_EXPR_ADD,
877                                         yasm_expr_expr(x86_ea->ea.disp.abs),
878                                         yasm_expr_int(delta), bc->line);
879            }
880            if (output_value(&x86_ea->ea.disp, *bufp, disp_len,
881                             (unsigned long)(*bufp-bufstart), bc, 1, d))
882                return 1;
883            *bufp += disp_len;
884        }
885    }
886
887    /* Immediate (if required) */
888    if (imm) {
889        unsigned int imm_len;
890        if (insn->postop == X86_POSTOP_SIGNEXT_IMM8) {
891            /* If we got here with this postop still set, we need to force
892             * imm size to 8 here.
893             */
894            imm->size = 8;
895            imm->sign = 1;
896            imm_len = 1;
897        } else
898            imm_len = imm->size/8;
899        if (output_value(imm, *bufp, imm_len, (unsigned long)(*bufp-bufstart),
900                         bc, 1, d))
901            return 1;
902        *bufp += imm_len;
903    }
904
905    return 0;
906}
907
908static int
909x86_bc_jmp_tobytes(yasm_bytecode *bc, unsigned char **bufp,
910                   unsigned char *bufstart, void *d,
911                   yasm_output_value_func output_value,
912                   /*@unused@*/ yasm_output_reloc_func output_reloc)
913{
914    x86_jmp *jmp = (x86_jmp *)bc->contents;
915    unsigned char opersize;
916    unsigned int i;
917    /*@only@*/ yasm_intnum *delta;
918
919    /* Prefixes */
920    x86_common_tobytes(&jmp->common, bufp, 0);
921
922    /* As opersize may be 0, figure out its "real" value. */
923    opersize = (jmp->common.opersize == 0) ?
924        jmp->common.mode_bits : jmp->common.opersize;
925
926    /* Check here again to see if forms are actually legal. */
927    switch (jmp->op_sel) {
928        case JMP_SHORT_FORCED:
929        case JMP_SHORT:
930            /* 1 byte relative displacement */
931            if (jmp->shortop.len == 0)
932                yasm_internal_error(N_("short jump does not exist"));
933
934            /* Opcode */
935            x86_opcode_tobytes(&jmp->shortop, bufp);
936
937            /* Adjust relative displacement to end of bytecode */
938            delta = yasm_intnum_create_int(-(long)bc->len);
939            if (!jmp->target.abs)
940                jmp->target.abs = yasm_expr_create_ident(yasm_expr_int(delta),
941                                                         bc->line);
942            else
943                jmp->target.abs =
944                    yasm_expr_create(YASM_EXPR_ADD,
945                                     yasm_expr_expr(jmp->target.abs),
946                                     yasm_expr_int(delta), bc->line);
947
948            jmp->target.size = 8;
949            jmp->target.sign = 1;
950            if (output_value(&jmp->target, *bufp, 1,
951                             (unsigned long)(*bufp-bufstart), bc, 1, d))
952                return 1;
953            *bufp += 1;
954            break;
955        case JMP_NEAR_FORCED:
956        case JMP_NEAR:
957            /* 2/4 byte relative displacement (depending on operand size) */
958            if (jmp->nearop.len == 0) {
959                yasm_error_set(YASM_ERROR_TYPE,
960                               N_("near jump does not exist"));
961                return 1;
962            }
963
964            /* Opcode */
965            x86_opcode_tobytes(&jmp->nearop, bufp);
966
967            i = (opersize == 16) ? 2 : 4;
968
969            /* Adjust relative displacement to end of bytecode */
970            delta = yasm_intnum_create_int(-(long)bc->len);
971            if (!jmp->target.abs)
972                jmp->target.abs = yasm_expr_create_ident(yasm_expr_int(delta),
973                                                         bc->line);
974            else
975                jmp->target.abs =
976                    yasm_expr_create(YASM_EXPR_ADD,
977                                     yasm_expr_expr(jmp->target.abs),
978                                     yasm_expr_int(delta), bc->line);
979
980            jmp->target.size = i*8;
981            jmp->target.sign = 1;
982            if (output_value(&jmp->target, *bufp, i,
983                             (unsigned long)(*bufp-bufstart), bc, 1, d))
984                return 1;
985            *bufp += i;
986            break;
987        case JMP_NONE:
988            yasm_internal_error(N_("jump op_sel cannot be JMP_NONE in tobytes"));
989        default:
990            yasm_internal_error(N_("unrecognized relative jump op_sel"));
991    }
992    return 0;
993}
994
995static int
996x86_bc_jmpfar_tobytes(yasm_bytecode *bc, unsigned char **bufp,
997                      unsigned char *bufstart, void *d,
998                      yasm_output_value_func output_value,
999                      /*@unused@*/ yasm_output_reloc_func output_reloc)
1000{
1001    x86_jmpfar *jmpfar = (x86_jmpfar *)bc->contents;
1002    unsigned int i;
1003    unsigned char opersize;
1004
1005    x86_common_tobytes(&jmpfar->common, bufp, 0);
1006    x86_opcode_tobytes(&jmpfar->opcode, bufp);
1007
1008    /* As opersize may be 0, figure out its "real" value. */
1009    opersize = (jmpfar->common.opersize == 0) ?
1010        jmpfar->common.mode_bits : jmpfar->common.opersize;
1011
1012    /* Absolute displacement: segment and offset */
1013    i = (opersize == 16) ? 2 : 4;
1014    jmpfar->offset.size = i*8;
1015    if (output_value(&jmpfar->offset, *bufp, i,
1016                     (unsigned long)(*bufp-bufstart), bc, 1, d))
1017        return 1;
1018    *bufp += i;
1019    jmpfar->segment.size = 16;
1020    if (output_value(&jmpfar->segment, *bufp, 2,
1021                     (unsigned long)(*bufp-bufstart), bc, 1, d))
1022        return 1;
1023    *bufp += 2;
1024
1025    return 0;
1026}
1027
1028int
1029yasm_x86__intnum_tobytes(yasm_arch *arch, const yasm_intnum *intn,
1030                         unsigned char *buf, size_t destsize, size_t valsize,
1031                         int shift, const yasm_bytecode *bc, int warn)
1032{
1033    /* Write value out. */
1034    yasm_intnum_get_sized(intn, buf, destsize, valsize, shift, 0, warn);
1035    return 0;
1036}
1037