Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. /*
  2.  *  i386 specific functions for TCC assembler
  3.  *
  4.  *  Copyright (c) 2001, 2002 Fabrice Bellard
  5.  *
  6.  * This library is free software; you can redistribute it and/or
  7.  * modify it under the terms of the GNU Lesser General Public
  8.  * License as published by the Free Software Foundation; either
  9.  * version 2 of the License, or (at your option) any later version.
  10.  *
  11.  * This library is distributed in the hope that it will be useful,
  12.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14.  * Lesser General Public License for more details.
  15.  *
  16.  * You should have received a copy of the GNU Lesser General Public
  17.  * License along with this library; if not, write to the Free Software
  18.  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  19.  */
  20.  
  21. #define MAX_OPERANDS 3
  22.  
  23. typedef struct ASMInstr {
  24.     uint16_t sym;
  25.     uint16_t opcode;
  26.     uint16_t instr_type;
  27. #define OPC_JMP       0x01  /* jmp operand */
  28. #define OPC_B         0x02  /* only used zith OPC_WL */
  29. #define OPC_WL        0x04  /* accepts w, l or no suffix */
  30. #define OPC_BWL       (OPC_B | OPC_WL) /* accepts b, w, l or no suffix */
  31. #define OPC_REG       0x08 /* register is added to opcode */
  32. #define OPC_MODRM     0x10 /* modrm encoding */
  33. #define OPC_FWAIT     0x20 /* add fwait opcode */
  34. #define OPC_TEST      0x40 /* test opcodes */
  35. #define OPC_SHIFT     0x80 /* shift opcodes */
  36. #define OPC_D16      0x0100 /* generate data16 prefix */
  37. #define OPC_ARITH    0x0200 /* arithmetic opcodes */
  38. #define OPC_SHORTJMP 0x0400 /* short jmp operand */
  39. #define OPC_FARITH   0x0800 /* FPU arithmetic opcodes */
  40. #define OPC_GROUP_SHIFT 13
  41.  
  42. /* in order to compress the operand type, we use specific operands and
  43.    we or only with EA  */
  44. #define OPT_REG8  0 /* warning: value is hardcoded from TOK_ASM_xxx */
  45. #define OPT_REG16 1 /* warning: value is hardcoded from TOK_ASM_xxx */
  46. #define OPT_REG32 2 /* warning: value is hardcoded from TOK_ASM_xxx */
  47. #define OPT_MMX   3 /* warning: value is hardcoded from TOK_ASM_xxx */
  48. #define OPT_SSE   4 /* warning: value is hardcoded from TOK_ASM_xxx */
  49. #define OPT_CR    5 /* warning: value is hardcoded from TOK_ASM_xxx */
  50. #define OPT_TR    6 /* warning: value is hardcoded from TOK_ASM_xxx */
  51. #define OPT_DB    7 /* warning: value is hardcoded from TOK_ASM_xxx */
  52. #define OPT_SEG   8
  53. #define OPT_ST    9
  54. #define OPT_IM8   10
  55. #define OPT_IM8S  11
  56. #define OPT_IM16  12
  57. #define OPT_IM32  13
  58. #define OPT_EAX   14 /* %al, %ax or %eax register */
  59. #define OPT_ST0   15 /* %st(0) register */
  60. #define OPT_CL    16 /* %cl register */
  61. #define OPT_DX    17 /* %dx register */
  62. #define OPT_ADDR  18 /* OP_EA with only offset */
  63. #define OPT_INDIR 19 /* *(expr) */
  64.  
  65. /* composite types */
  66. #define OPT_COMPOSITE_FIRST   20
  67. #define OPT_IM       20 /* IM8 | IM16 | IM32 */
  68. #define OPT_REG      21 /* REG8 | REG16 | REG32 */
  69. #define OPT_REGW     22 /* REG16 | REG32 */
  70. #define OPT_IMW      23 /* IM16 | IM32 */
  71.  
  72. /* can be ored with any OPT_xxx */
  73. #define OPT_EA    0x80
  74.  
  75.     uint8_t nb_ops;
  76.     uint8_t op_type[MAX_OPERANDS]; /* see OP_xxx */
  77. } ASMInstr;
  78.  
  79. typedef struct Operand {
  80.     uint32_t type;
  81. #define OP_REG8   (1 << OPT_REG8)
  82. #define OP_REG16  (1 << OPT_REG16)
  83. #define OP_REG32  (1 << OPT_REG32)
  84. #define OP_MMX    (1 << OPT_MMX)
  85. #define OP_SSE    (1 << OPT_SSE)
  86. #define OP_CR     (1 << OPT_CR)
  87. #define OP_TR     (1 << OPT_TR)
  88. #define OP_DB     (1 << OPT_DB)
  89. #define OP_SEG    (1 << OPT_SEG)
  90. #define OP_ST     (1 << OPT_ST)
  91. #define OP_IM8    (1 << OPT_IM8)
  92. #define OP_IM8S   (1 << OPT_IM8S)
  93. #define OP_IM16   (1 << OPT_IM16)
  94. #define OP_IM32   (1 << OPT_IM32)
  95. #define OP_EAX    (1 << OPT_EAX)
  96. #define OP_ST0    (1 << OPT_ST0)
  97. #define OP_CL     (1 << OPT_CL)
  98. #define OP_DX     (1 << OPT_DX)
  99. #define OP_ADDR   (1 << OPT_ADDR)
  100. #define OP_INDIR  (1 << OPT_INDIR)
  101.  
  102. #define OP_EA     0x40000000
  103. #define OP_REG    (OP_REG8 | OP_REG16 | OP_REG32)
  104. #define OP_IM     OP_IM32
  105.     int8_t  reg; /* register, -1 if none */
  106.     int8_t  reg2; /* second register, -1 if none */
  107.     uint8_t shift;
  108.     ExprValue e;
  109. } Operand;
  110.  
  111. static const uint8_t reg_to_size[5] = {
  112.     [OP_REG8] = 0,
  113.     [OP_REG16] = 1,
  114.     [OP_REG32] = 2,
  115. };
  116.    
  117. #define WORD_PREFIX_OPCODE 0x66
  118.  
  119. #define NB_TEST_OPCODES 30
  120.  
  121. static const uint8_t test_bits[NB_TEST_OPCODES] = {
  122.  0x00, /* o */
  123.  0x01, /* no */
  124.  0x02, /* b */
  125.  0x02, /* c */
  126.  0x02, /* nae */
  127.  0x03, /* nb */
  128.  0x03, /* nc */
  129.  0x03, /* ae */
  130.  0x04, /* e */
  131.  0x04, /* z */
  132.  0x05, /* ne */
  133.  0x05, /* nz */
  134.  0x06, /* be */
  135.  0x06, /* na */
  136.  0x07, /* nbe */
  137.  0x07, /* a */
  138.  0x08, /* s */
  139.  0x09, /* ns */
  140.  0x0a, /* p */
  141.  0x0a, /* pe */
  142.  0x0b, /* np */
  143.  0x0b, /* po */
  144.  0x0c, /* l */
  145.  0x0c, /* nge */
  146.  0x0d, /* nl */
  147.  0x0d, /* ge */
  148.  0x0e, /* le */
  149.  0x0e, /* ng */
  150.  0x0f, /* nle */
  151.  0x0f, /* g */
  152. };
  153.  
  154. static const ASMInstr asm_instrs[] = {
  155. #define ALT(x) x
  156. #define DEF_ASM_OP0(name, opcode)
  157. #define DEF_ASM_OP0L(name, opcode, group, instr_type) { TOK_ASM_ ## name, opcode, (instr_type | group << OPC_GROUP_SHIFT), 0 },
  158. #define DEF_ASM_OP1(name, opcode, group, instr_type, op0) { TOK_ASM_ ## name, opcode, (instr_type | group << OPC_GROUP_SHIFT), 1, { op0 }},
  159. #define DEF_ASM_OP2(name, opcode, group, instr_type, op0, op1) { TOK_ASM_ ## name, opcode, (instr_type | group << OPC_GROUP_SHIFT), 2, { op0, op1 }},
  160. #define DEF_ASM_OP3(name, opcode, group, instr_type, op0, op1, op2) { TOK_ASM_ ## name, opcode, (instr_type | group << OPC_GROUP_SHIFT), 3, { op0, op1, op2 }},
  161. #include "i386-asm.h"
  162.  
  163.     /* last operation */
  164.     { 0, },
  165. };
  166.  
  167. static const uint16_t op0_codes[] = {
  168. #define ALT(x)
  169. #define DEF_ASM_OP0(x, opcode) opcode,
  170. #define DEF_ASM_OP0L(name, opcode, group, instr_type)
  171. #define DEF_ASM_OP1(name, opcode, group, instr_type, op0)
  172. #define DEF_ASM_OP2(name, opcode, group, instr_type, op0, op1)
  173. #define DEF_ASM_OP3(name, opcode, group, instr_type, op0, op1, op2)
  174. #include "i386-asm.h"
  175. };
  176.  
  177. static inline int get_reg_shift(TCCState *s1)
  178. {
  179.     int shift, v;
  180.  
  181.     v = asm_int_expr(s1);
  182.     switch(v) {
  183.     case 1:
  184.         shift = 0;
  185.         break;
  186.     case 2:
  187.         shift = 1;
  188.         break;
  189.     case 4:
  190.         shift = 2;
  191.         break;
  192.     case 8:
  193.         shift = 3;
  194.         break;
  195.     default:
  196.         expect("1, 2, 4 or 8 constant");
  197.         shift = 0;
  198.         break;
  199.     }
  200.     return shift;
  201. }
  202.  
  203. static int asm_parse_reg(void)
  204. {
  205.     int reg;
  206.     if (tok != '%')
  207.         goto error_32;
  208.     next();
  209.     if (tok >= TOK_ASM_eax && tok <= TOK_ASM_edi) {
  210.         reg = tok - TOK_ASM_eax;
  211.         next();
  212.         return reg;
  213.     } else {
  214.     error_32:
  215.         expect("32 bit register");
  216.         return 0;
  217.     }
  218. }
  219.  
  220. static void parse_operand(TCCState *s1, Operand *op)
  221. {
  222.     ExprValue e;
  223.     int reg, indir;
  224.     const char *p;
  225.  
  226.     indir = 0;
  227.     if (tok == '*') {
  228.         next();
  229.         indir = OP_INDIR;
  230.     }
  231.  
  232.     if (tok == '%') {
  233.         next();
  234.         if (tok >= TOK_ASM_al && tok <= TOK_ASM_db7) {
  235.             reg = tok - TOK_ASM_al;
  236.             op->type = 1 << (reg >> 3); /* WARNING: do not change constant order */
  237.             op->reg = reg & 7;
  238.             if ((op->type & OP_REG) && op->reg == TREG_EAX)
  239.                 op->type |= OP_EAX;
  240.             else if (op->type == OP_REG8 && op->reg == TREG_ECX)
  241.                 op->type |= OP_CL;
  242.             else if (op->type == OP_REG16 && op->reg == TREG_EDX)
  243.                 op->type |= OP_DX;
  244.         } else if (tok >= TOK_ASM_dr0 && tok <= TOK_ASM_dr7) {
  245.             op->type = OP_DB;
  246.             op->reg = tok - TOK_ASM_dr0;
  247.         } else if (tok >= TOK_ASM_es && tok <= TOK_ASM_gs) {
  248.             op->type = OP_SEG;
  249.             op->reg = tok - TOK_ASM_es;
  250.         } else if (tok == TOK_ASM_st) {
  251.             op->type = OP_ST;
  252.             op->reg = 0;
  253.             next();
  254.             if (tok == '(') {
  255.                 next();
  256.                 if (tok != TOK_PPNUM)
  257.                     goto reg_error;
  258.                 p = tokc.cstr->data;
  259.                 reg = p[0] - '0';
  260.                 if ((unsigned)reg >= 8 || p[1] != '\0')
  261.                     goto reg_error;
  262.                 op->reg = reg;
  263.                 next();
  264.                 skip(')');
  265.             }
  266.             if (op->reg == 0)
  267.                 op->type |= OP_ST0;
  268.             goto no_skip;
  269.         } else {
  270.         reg_error:
  271.             error("unknown register");
  272.         }
  273.         next();
  274.     no_skip: ;
  275.     } else if (tok == '$') {
  276.         /* constant value */
  277.         next();
  278.         asm_expr(s1, &e);
  279.         op->type = OP_IM32;
  280.         op->e.v = e.v;
  281.         op->e.sym = e.sym;
  282.         if (!op->e.sym) {
  283.             if (op->e.v == (uint8_t)op->e.v)
  284.                 op->type |= OP_IM8;
  285.             if (op->e.v == (int8_t)op->e.v)
  286.                 op->type |= OP_IM8S;
  287.             if (op->e.v == (uint16_t)op->e.v)
  288.                 op->type |= OP_IM16;
  289.         }
  290.     } else {
  291.         /* address(reg,reg2,shift) with all variants */
  292.         op->type = OP_EA;
  293.         op->reg = -1;
  294.         op->reg2 = -1;
  295.         op->shift = 0;
  296.         if (tok != '(') {
  297.             asm_expr(s1, &e);
  298.             op->e.v = e.v;
  299.             op->e.sym = e.sym;
  300.         } else {
  301.             op->e.v = 0;
  302.             op->e.sym = NULL;
  303.         }
  304.         if (tok == '(') {
  305.             next();
  306.             if (tok != ',') {
  307.                 op->reg = asm_parse_reg();
  308.             }
  309.             if (tok == ',') {
  310.                 next();
  311.                 if (tok != ',') {
  312.                     op->reg2 = asm_parse_reg();
  313.                 }
  314.                 skip(',');
  315.                 op->shift = get_reg_shift(s1);
  316.             }
  317.             skip(')');
  318.         }
  319.         if (op->reg == -1 && op->reg2 == -1)
  320.             op->type |= OP_ADDR;
  321.     }
  322.     op->type |= indir;
  323. }
  324.  
  325. /* XXX: unify with C code output ? */
  326. static void gen_expr32(ExprValue *pe)
  327. {
  328.     if (pe->sym)
  329.         greloc(cur_text_section, pe->sym, ind, R_386_32);
  330.     gen_le32(pe->v);
  331. }
  332.  
  333. /* XXX: unify with C code output ? */
  334. static void gen_disp32(ExprValue *pe)
  335. {
  336.     Sym *sym;
  337.     sym = pe->sym;
  338.     if (sym) {
  339.         if (sym->r == cur_text_section->sh_num) {
  340.             /* same section: we can output an absolute value. Note
  341.                that the TCC compiler behaves differently here because
  342.                it always outputs a relocation to ease (future) code
  343.                elimination in the linker */
  344.             gen_le32(pe->v + (long)sym->next - ind - 4);
  345.         } else {
  346.             greloc(cur_text_section, sym, ind, R_386_PC32);
  347.             gen_le32(pe->v - 4);
  348.         }
  349.     } else {
  350.         /* put an empty PC32 relocation */
  351.         put_elf_reloc(symtab_section, cur_text_section,
  352.                       ind, R_386_PC32, 0);
  353.         gen_le32(pe->v - 4);
  354.     }
  355. }
  356.  
  357.  
  358. static void gen_le16(int v)
  359. {
  360.     g(v);
  361.     g(v >> 8);
  362. }
  363.  
  364. /* generate the modrm operand */
  365. static inline void asm_modrm(int reg, Operand *op)
  366. {
  367.     int mod, reg1, reg2, sib_reg1;
  368.  
  369.     if (op->type & (OP_REG | OP_MMX | OP_SSE)) {
  370.         g(0xc0 + (reg << 3) + op->reg);
  371.     } else if (op->reg == -1 && op->reg2 == -1) {
  372.         /* displacement only */
  373.         g(0x05 + (reg << 3));
  374.         gen_expr32(&op->e);
  375.     } else {
  376.         sib_reg1 = op->reg;
  377.         /* fist compute displacement encoding */
  378.         if (sib_reg1 == -1) {
  379.             sib_reg1 = 5;
  380.             mod = 0x00;
  381.         } else if (op->e.v == 0 && !op->e.sym && op->reg != 5) {
  382.             mod = 0x00;
  383.         } else if (op->e.v == (int8_t)op->e.v && !op->e.sym) {
  384.             mod = 0x40;
  385.         } else {
  386.             mod = 0x80;
  387.         }
  388.         /* compute if sib byte needed */
  389.         reg1 = op->reg;
  390.         if (op->reg2 != -1)
  391.             reg1 = 4;
  392.         g(mod + (reg << 3) + reg1);
  393.         if (reg1 == 4) {
  394.             /* add sib byte */
  395.             reg2 = op->reg2;
  396.             if (reg2 == -1)
  397.                 reg2 = 4; /* indicate no index */
  398.             g((op->shift << 6) + (reg2 << 3) + sib_reg1);
  399.         }
  400.  
  401.         /* add offset */
  402.         if (mod == 0x40) {
  403.             g(op->e.v);
  404.         } else if (mod == 0x80 || op->reg == -1) {
  405.             gen_expr32(&op->e);
  406.         }
  407.     }
  408. }
  409.  
  410. static void asm_opcode(TCCState *s1, int opcode)
  411. {
  412.     const ASMInstr *pa;
  413.     int i, modrm_index, reg, v, op1, is_short_jmp;
  414.     int nb_ops, s, ss;
  415.     Operand ops[MAX_OPERANDS], *pop;
  416.     int op_type[3]; /* decoded op type */
  417.  
  418.     /* get operands */
  419.     pop = ops;
  420.     nb_ops = 0;
  421.     for(;;) {
  422.         if (tok == ';' || tok == TOK_LINEFEED)
  423.             break;
  424.         if (nb_ops >= MAX_OPERANDS) {
  425.             error("incorrect number of operands");
  426.         }
  427.         parse_operand(s1, pop);
  428.         pop++;
  429.         nb_ops++;
  430.         if (tok != ',')
  431.             break;
  432.         next();
  433.     }
  434.  
  435.     is_short_jmp = 0;
  436.     s = 0; /* avoid warning */
  437.    
  438.     /* optimize matching by using a lookup table (no hashing is needed
  439.        !) */
  440.     for(pa = asm_instrs; pa->sym != 0; pa++) {
  441.         s = 0;
  442.         if (pa->instr_type & OPC_FARITH) {
  443.             v = opcode - pa->sym;
  444.             if (!((unsigned)v < 8 * 6 && (v % 6) == 0))
  445.                 continue;
  446.         } else if (pa->instr_type & OPC_ARITH) {
  447.             if (!(opcode >= pa->sym && opcode < pa->sym + 8 * 4))
  448.                 continue;
  449.             goto compute_size;
  450.         } else if (pa->instr_type & OPC_SHIFT) {
  451.             if (!(opcode >= pa->sym && opcode < pa->sym + 7 * 4))
  452.                 continue;
  453.             goto compute_size;
  454.         } else if (pa->instr_type & OPC_TEST) {
  455.             if (!(opcode >= pa->sym && opcode < pa->sym + NB_TEST_OPCODES))
  456.                 continue;
  457.         } else if (pa->instr_type & OPC_B) {
  458.             if (!(opcode >= pa->sym && opcode <= pa->sym + 3))
  459.                 continue;
  460.         compute_size:
  461.             s = (opcode - pa->sym) & 3;
  462.         } else if (pa->instr_type & OPC_WL) {
  463.             if (!(opcode >= pa->sym && opcode <= pa->sym + 2))
  464.                 continue;
  465.             s = opcode - pa->sym + 1;
  466.         } else {
  467.             if (pa->sym != opcode)
  468.                 continue;
  469.         }
  470.         if (pa->nb_ops != nb_ops)
  471.             continue;
  472.         /* now decode and check each operand */
  473.         for(i = 0; i < nb_ops; i++) {
  474.             int op1, op2;
  475.             op1 = pa->op_type[i];
  476.             op2 = op1 & 0x1f;
  477.             switch(op2) {
  478.             case OPT_IM:
  479.                 v = OP_IM8 | OP_IM16 | OP_IM32;
  480.                 break;
  481.             case OPT_REG:
  482.                 v = OP_REG8 | OP_REG16 | OP_REG32;
  483.                 break;
  484.             case OPT_REGW:
  485.                 v = OP_REG16 | OP_REG32;
  486.                 break;
  487.             case OPT_IMW:
  488.                 v = OP_IM16 | OP_IM32;
  489.                 break;
  490.             default:
  491.                 v = 1 << op2;
  492.                 break;
  493.             }
  494.             if (op1 & OPT_EA)
  495.                 v |= OP_EA;
  496.             op_type[i] = v;
  497.             if ((ops[i].type & v) == 0)
  498.                 goto next;
  499.         }
  500.         /* all is matching ! */
  501.         break;
  502.     next: ;
  503.     }
  504.     if (pa->sym == 0) {
  505.         if (opcode >= TOK_ASM_pusha && opcode <= TOK_ASM_emms) {
  506.             int b;
  507.             b = op0_codes[opcode - TOK_ASM_pusha];
  508.             if (b & 0xff00)
  509.                 g(b >> 8);
  510.             g(b);
  511.             return;
  512.         } else {
  513.             error("unknown opcode '%s'",
  514.                   get_tok_str(opcode, NULL));
  515.         }
  516.     }
  517.     /* if the size is unknown, then evaluate it (OPC_B or OPC_WL case) */
  518.     if (s == 3) {
  519.         for(i = 0; s == 3 && i < nb_ops; i++) {
  520.             if ((ops[i].type & OP_REG) && !(op_type[i] & (OP_CL | OP_DX)))
  521.                 s = reg_to_size[ops[i].type & OP_REG];
  522.         }
  523.         if (s == 3) {
  524.             if ((opcode == TOK_ASM_push || opcode == TOK_ASM_pop) &&
  525.                 (ops[0].type & (OP_SEG | OP_IM8S | OP_IM32)))
  526.                 s = 2;
  527.             else
  528.                 error("cannot infer opcode suffix");
  529.         }
  530.     }
  531.  
  532.     /* generate data16 prefix if needed */
  533.     ss = s;
  534.     if (s == 1 || (pa->instr_type & OPC_D16))
  535.         g(WORD_PREFIX_OPCODE);
  536.     else if (s == 2)
  537.         s = 1;
  538.     /* now generates the operation */
  539.     if (pa->instr_type & OPC_FWAIT)
  540.         g(0x9b);
  541.  
  542.     v = pa->opcode;
  543.     if (v == 0x69 || v == 0x69) {
  544.         /* kludge for imul $im, %reg */
  545.         nb_ops = 3;
  546.         ops[2] = ops[1];
  547.     } else if (v == 0xcd && ops[0].e.v == 3 && !ops[0].e.sym) {
  548.         v--; /* int $3 case */
  549.         nb_ops = 0;
  550.     } else if ((v == 0x06 || v == 0x07)) {
  551.         if (ops[0].reg >= 4) {
  552.             /* push/pop %fs or %gs */
  553.             v = 0x0fa0 + (v - 0x06) + ((ops[0].reg - 4) << 3);
  554.         } else {
  555.             v += ops[0].reg << 3;
  556.         }
  557.         nb_ops = 0;
  558.     } else if (v <= 0x05) {
  559.         /* arith case */
  560.         v += ((opcode - TOK_ASM_addb) >> 2) << 3;
  561.     } else if ((pa->instr_type & (OPC_FARITH | OPC_MODRM)) == OPC_FARITH) {
  562.         /* fpu arith case */
  563.         v += ((opcode - pa->sym) / 6) << 3;
  564.     }
  565.     if (pa->instr_type & OPC_REG) {
  566.         for(i = 0; i < nb_ops; i++) {
  567.             if (op_type[i] & (OP_REG | OP_ST)) {
  568.                 v += ops[i].reg;
  569.                 break;
  570.             }
  571.         }
  572.         /* mov $im, %reg case */
  573.         if (pa->opcode == 0xb0 && s >= 1)
  574.             v += 7;
  575.     }
  576.     if (pa->instr_type & OPC_B)
  577.         v += s;
  578.     if (pa->instr_type & OPC_TEST)
  579.         v += test_bits[opcode - pa->sym];
  580.     if (pa->instr_type & OPC_SHORTJMP) {
  581.         Sym *sym;
  582.         int jmp_disp;
  583.  
  584.         /* see if we can really generate the jump with a byte offset */
  585.         sym = ops[0].e.sym;
  586.         if (!sym)
  587.             goto no_short_jump;
  588.         if (sym->r != cur_text_section->sh_num)
  589.             goto no_short_jump;
  590.         jmp_disp = ops[0].e.v + (long)sym->next - ind - 2;
  591.         if (jmp_disp == (int8_t)jmp_disp) {
  592.             /* OK to generate jump */
  593.             is_short_jmp = 1;
  594.             ops[0].e.v = jmp_disp;
  595.         } else {
  596.         no_short_jump:
  597.             if (pa->instr_type & OPC_JMP) {
  598.                 /* long jump will be allowed. need to modify the
  599.                    opcode slightly */
  600.                 if (v == 0xeb)
  601.                     v = 0xe9;
  602.                 else
  603.                     v += 0x0f10;
  604.             } else {
  605.                 error("invalid displacement");
  606.             }
  607.         }
  608.     }
  609.     op1 = v >> 8;
  610.     if (op1)
  611.         g(op1);
  612.     g(v);
  613.        
  614.     /* search which operand will used for modrm */
  615.     modrm_index = 0;
  616.     if (pa->instr_type & OPC_SHIFT) {
  617.         reg = (opcode - pa->sym) >> 2;
  618.         if (reg == 6)
  619.             reg = 7;
  620.     } else if (pa->instr_type & OPC_ARITH) {
  621.         reg = (opcode - pa->sym) >> 2;
  622.     } else if (pa->instr_type & OPC_FARITH) {
  623.         reg = (opcode - pa->sym) / 6;
  624.     } else {
  625.         reg = (pa->instr_type >> OPC_GROUP_SHIFT) & 7;
  626.     }
  627.     if (pa->instr_type & OPC_MODRM) {
  628.         /* first look for an ea operand */
  629.         for(i = 0;i < nb_ops; i++) {
  630.             if (op_type[i] & OP_EA)
  631.                 goto modrm_found;
  632.         }
  633.         /* then if not found, a register or indirection (shift instructions) */
  634.         for(i = 0;i < nb_ops; i++) {
  635.             if (op_type[i] & (OP_REG | OP_MMX | OP_SSE | OP_INDIR))
  636.                 goto modrm_found;
  637.         }
  638. #ifdef ASM_DEBUG
  639.         error("bad op table");
  640. #endif      
  641.     modrm_found:
  642.         modrm_index = i;
  643.         /* if a register is used in another operand then it is
  644.            used instead of group */
  645.         for(i = 0;i < nb_ops; i++) {
  646.             v = op_type[i];
  647.             if (i != modrm_index &&
  648.                 (v & (OP_REG | OP_MMX | OP_SSE | OP_CR | OP_TR | OP_DB | OP_SEG))) {
  649.                 reg = ops[i].reg;
  650.                 break;
  651.             }
  652.         }
  653.  
  654.         asm_modrm(reg, &ops[modrm_index]);
  655.     }
  656.  
  657.     /* emit constants */
  658.     if (pa->opcode == 0x9a || pa->opcode == 0xea) {
  659.         /* ljmp or lcall kludge */
  660.         gen_expr32(&ops[1].e);
  661.         if (ops[0].e.sym)
  662.             error("cannot relocate");
  663.         gen_le16(ops[0].e.v);
  664.     } else {
  665.         for(i = 0;i < nb_ops; i++) {
  666.             v = op_type[i];
  667.             if (v & (OP_IM8 | OP_IM16 | OP_IM32 | OP_IM8S | OP_ADDR)) {
  668.                 /* if multiple sizes are given it means we must look
  669.                    at the op size */
  670.                 if (v == (OP_IM8 | OP_IM16 | OP_IM32) ||
  671.                     v == (OP_IM16 | OP_IM32)) {
  672.                     if (ss == 0)
  673.                         v = OP_IM8;
  674.                     else if (ss == 1)
  675.                         v = OP_IM16;
  676.                     else
  677.                         v = OP_IM32;
  678.                 }
  679.                 if (v & (OP_IM8 | OP_IM8S)) {
  680.                     if (ops[i].e.sym)
  681.                         goto error_relocate;
  682.                     g(ops[i].e.v);
  683.                 } else if (v & OP_IM16) {
  684.                     if (ops[i].e.sym) {
  685.                     error_relocate:
  686.                         error("cannot relocate");
  687.                     }
  688.                     gen_le16(ops[i].e.v);
  689.                 } else {
  690.                     if (pa->instr_type & (OPC_JMP | OPC_SHORTJMP)) {
  691.                         if (is_short_jmp)
  692.                             g(ops[i].e.v);
  693.                         else
  694.                             gen_disp32(&ops[i].e);
  695.                     } else {
  696.                         gen_expr32(&ops[i].e);
  697.                     }
  698.                 }
  699.             }
  700.         }
  701.     }
  702. }
  703.  
  704. #define NB_SAVED_REGS 3
  705. #define NB_ASM_REGS 8
  706.  
  707. /* return the constraint priority (we allocate first the lowest
  708.    numbered constraints) */
  709. static inline int constraint_priority(const char *str)
  710. {
  711.     int priority, c, pr;
  712.  
  713.     /* we take the lowest priority */
  714.     priority = 0;
  715.     for(;;) {
  716.         c = *str;
  717.         if (c == '\0')
  718.             break;
  719.         str++;
  720.         switch(c) {
  721.         case 'A':
  722.             pr = 0;
  723.             break;
  724.         case 'a':
  725.         case 'b':
  726.         case 'c':
  727.         case 'd':
  728.         case 'S':
  729.         case 'D':
  730.             pr = 1;
  731.             break;
  732.         case 'q':
  733.             pr = 2;
  734.             break;
  735.         case 'r':
  736.             pr = 3;
  737.             break;
  738.         case 'N':
  739.         case 'M':
  740.         case 'I':
  741.         case 'i':
  742.         case 'm':
  743.         case 'g':
  744.             pr = 4;
  745.             break;
  746.         default:
  747.             error("unknown constraint '%c'", c);
  748.             pr = 0;
  749.         }
  750.         if (pr > priority)
  751.             priority = pr;
  752.     }
  753.     return priority;
  754. }
  755.  
  756. static const char *skip_constraint_modifiers(const char *p)
  757. {
  758.     while (*p == '=' || *p == '&' || *p == '+' || *p == '%')
  759.         p++;
  760.     return p;
  761. }
  762.  
  763. #define REG_OUT_MASK 0x01
  764. #define REG_IN_MASK  0x02
  765.  
  766. #define is_reg_allocated(reg) (regs_allocated[reg] & reg_mask)
  767.  
  768. static void asm_compute_constraints(ASMOperand *operands,
  769.                                     int nb_operands, int nb_outputs,
  770.                                     const uint8_t *clobber_regs,
  771.                                     int *pout_reg)
  772. {
  773.     ASMOperand *op;
  774.     int sorted_op[MAX_ASM_OPERANDS];
  775.     int i, j, k, p1, p2, tmp, reg, c, reg_mask;
  776.     const char *str;
  777.     uint8_t regs_allocated[NB_ASM_REGS];
  778.    
  779.     /* init fields */
  780.     for(i=0;i<nb_operands;i++) {
  781.         op = &operands[i];
  782.         op->input_index = -1;
  783.         op->ref_index = -1;
  784.         op->reg = -1;
  785.         op->is_memory = 0;
  786.         op->is_rw = 0;
  787.     }
  788.     /* compute constraint priority and evaluate references to output
  789.        constraints if input constraints */
  790.     for(i=0;i<nb_operands;i++) {
  791.         op = &operands[i];
  792.         str = op->constraint;
  793.         str = skip_constraint_modifiers(str);
  794.         if (isnum(*str) || *str == '[') {
  795.             /* this is a reference to another constraint */
  796.             k = find_constraint(operands, nb_operands, str, NULL);
  797.             if ((unsigned)k >= i || i < nb_outputs)
  798.                 error("invalid reference in constraint %d ('%s')",
  799.                       i, str);
  800.             op->ref_index = k;
  801.             if (operands[k].input_index >= 0)
  802.                 error("cannot reference twice the same operand");
  803.             operands[k].input_index = i;
  804.             op->priority = 5;
  805.         } else {
  806.             op->priority = constraint_priority(str);
  807.         }
  808.     }
  809.    
  810.     /* sort operands according to their priority */
  811.     for(i=0;i<nb_operands;i++)
  812.         sorted_op[i] = i;
  813.     for(i=0;i<nb_operands - 1;i++) {
  814.         for(j=i+1;j<nb_operands;j++) {
  815.             p1 = operands[sorted_op[i]].priority;
  816.             p2 = operands[sorted_op[j]].priority;
  817.             if (p2 < p1) {
  818.                 tmp = sorted_op[i];
  819.                 sorted_op[i] = sorted_op[j];
  820.                 sorted_op[j] = tmp;
  821.             }
  822.         }
  823.     }
  824.  
  825.     for(i = 0;i < NB_ASM_REGS; i++) {
  826.         if (clobber_regs[i])
  827.             regs_allocated[i] = REG_IN_MASK | REG_OUT_MASK;
  828.         else
  829.             regs_allocated[i] = 0;
  830.     }
  831.     /* esp cannot be used */
  832.     regs_allocated[4] = REG_IN_MASK | REG_OUT_MASK;
  833.     /* ebp cannot be used yet */
  834.     regs_allocated[5] = REG_IN_MASK | REG_OUT_MASK;
  835.  
  836.     /* allocate registers and generate corresponding asm moves */
  837.     for(i=0;i<nb_operands;i++) {
  838.         j = sorted_op[i];
  839.         op = &operands[j];
  840.         str = op->constraint;
  841.         /* no need to allocate references */
  842.         if (op->ref_index >= 0)
  843.             continue;
  844.         /* select if register is used for output, input or both */
  845.         if (op->input_index >= 0) {
  846.             reg_mask = REG_IN_MASK | REG_OUT_MASK;
  847.         } else if (j < nb_outputs) {
  848.             reg_mask = REG_OUT_MASK;
  849.         } else {
  850.             reg_mask = REG_IN_MASK;
  851.         }
  852.     try_next:
  853.         c = *str++;
  854.         switch(c) {
  855.         case '=':
  856.             goto try_next;
  857.         case '+':
  858.             op->is_rw = 1;
  859.             /* FALL THRU */
  860.         case '&':
  861.             if (j >= nb_outputs)
  862.                 error("'%c' modifier can only be applied to outputs", c);
  863.             reg_mask = REG_IN_MASK | REG_OUT_MASK;
  864.             goto try_next;
  865.         case 'A':
  866.             /* allocate both eax and edx */
  867.             if (is_reg_allocated(TREG_EAX) ||
  868.                 is_reg_allocated(TREG_EDX))
  869.                 goto try_next;
  870.             op->is_llong = 1;
  871.             op->reg = TREG_EAX;
  872.             regs_allocated[TREG_EAX] |= reg_mask;
  873.             regs_allocated[TREG_EDX] |= reg_mask;
  874.             break;
  875.         case 'a':
  876.             reg = TREG_EAX;
  877.             goto alloc_reg;
  878.         case 'b':
  879.             reg = 3;
  880.             goto alloc_reg;
  881.         case 'c':
  882.             reg = TREG_ECX;
  883.             goto alloc_reg;
  884.         case 'd':
  885.             reg = TREG_EDX;
  886.             goto alloc_reg;
  887.         case 'S':
  888.             reg = 6;
  889.             goto alloc_reg;
  890.         case 'D':
  891.             reg = 7;
  892.         alloc_reg:
  893.             if (is_reg_allocated(reg))
  894.                 goto try_next;
  895.             goto reg_found;
  896.         case 'q':
  897.             /* eax, ebx, ecx or edx */
  898.             for(reg = 0; reg < 4; reg++) {
  899.                 if (!is_reg_allocated(reg))
  900.                     goto reg_found;
  901.             }
  902.             goto try_next;
  903.         case 'r':
  904.             /* any general register */
  905.             for(reg = 0; reg < 8; reg++) {
  906.                 if (!is_reg_allocated(reg))
  907.                     goto reg_found;
  908.             }
  909.             goto try_next;
  910.         reg_found:
  911.             /* now we can reload in the register */
  912.             op->is_llong = 0;
  913.             op->reg = reg;
  914.             regs_allocated[reg] |= reg_mask;
  915.             break;
  916.         case 'i':
  917.             if (!((op->vt->r & (VT_VALMASK | VT_LVAL)) == VT_CONST))
  918.                 goto try_next;
  919.             break;
  920.         case 'I':
  921.         case 'N':
  922.         case 'M':
  923.             if (!((op->vt->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST))
  924.                 goto try_next;
  925.             break;
  926.         case 'm':
  927.         case 'g':
  928.             /* nothing special to do because the operand is already in
  929.                memory, except if the pointer itself is stored in a
  930.                memory variable (VT_LLOCAL case) */
  931.             /* XXX: fix constant case */
  932.             /* if it is a reference to a memory zone, it must lie
  933.                in a register, so we reserve the register in the
  934.                input registers and a load will be generated
  935.                later */
  936.             if (j < nb_outputs || c == 'm') {
  937.                 if ((op->vt->r & VT_VALMASK) == VT_LLOCAL) {
  938.                     /* any general register */
  939.                     for(reg = 0; reg < 8; reg++) {
  940.                         if (!(regs_allocated[reg] & REG_IN_MASK))
  941.                             goto reg_found1;
  942.                     }
  943.                     goto try_next;
  944.                 reg_found1:
  945.                     /* now we can reload in the register */
  946.                     regs_allocated[reg] |= REG_IN_MASK;
  947.                     op->reg = reg;
  948.                     op->is_memory = 1;
  949.                 }
  950.             }
  951.             break;
  952.         default:
  953.             error("asm constraint %d ('%s') could not be satisfied",
  954.                   j, op->constraint);
  955.             break;
  956.         }
  957.         /* if a reference is present for that operand, we assign it too */
  958.         if (op->input_index >= 0) {
  959.             operands[op->input_index].reg = op->reg;
  960.             operands[op->input_index].is_llong = op->is_llong;
  961.         }
  962.     }
  963.    
  964.     /* compute out_reg. It is used to store outputs registers to memory
  965.        locations references by pointers (VT_LLOCAL case) */
  966.     *pout_reg = -1;
  967.     for(i=0;i<nb_operands;i++) {
  968.         op = &operands[i];
  969.         if (op->reg >= 0 &&
  970.             (op->vt->r & VT_VALMASK) == VT_LLOCAL  &&
  971.             !op->is_memory) {
  972.             for(reg = 0; reg < 8; reg++) {
  973.                 if (!(regs_allocated[reg] & REG_OUT_MASK))
  974.                     goto reg_found2;
  975.             }
  976.             error("could not find free output register for reloading");
  977.         reg_found2:
  978.             *pout_reg = reg;
  979.             break;
  980.         }
  981.     }
  982.    
  983.     /* print sorted constraints */
  984. #ifdef ASM_DEBUG
  985.     for(i=0;i<nb_operands;i++) {
  986.         j = sorted_op[i];
  987.         op = &operands[j];
  988.         printf("%%%d [%s]: \"%s\" r=0x%04x reg=%d\n",
  989.                j,                
  990.                op->id ? get_tok_str(op->id, NULL) : "",
  991.                op->constraint,
  992.                op->vt->r,
  993.                op->reg);
  994.     }
  995.     if (*pout_reg >= 0)
  996.         printf("out_reg=%d\n", *pout_reg);
  997. #endif
  998. }
  999.  
  1000. static void subst_asm_operand(CString *add_str,
  1001.                               SValue *sv, int modifier)
  1002. {
  1003.     int r, reg, size, val;
  1004.     char buf[64];
  1005.  
  1006.     r = sv->r;
  1007.     if ((r & VT_VALMASK) == VT_CONST) {
  1008.         if (!(r & VT_LVAL) && modifier != 'c' && modifier != 'n')
  1009.             cstr_ccat(add_str, '$');
  1010.         if (r & VT_SYM) {
  1011.             cstr_cat(add_str, get_tok_str(sv->sym->v, NULL));
  1012.             if (sv->c.i != 0) {
  1013.                 cstr_ccat(add_str, '+');
  1014.             } else {
  1015.                 return;
  1016.             }
  1017.         }
  1018.         val = sv->c.i;
  1019.         if (modifier == 'n')
  1020.             val = -val;
  1021.         snprintf(buf, sizeof(buf), "%d", sv->c.i);
  1022.         cstr_cat(add_str, buf);
  1023.     } else if ((r & VT_VALMASK) == VT_LOCAL) {
  1024.         snprintf(buf, sizeof(buf), "%d(%%ebp)", sv->c.i);
  1025.         cstr_cat(add_str, buf);
  1026.     } else if (r & VT_LVAL) {
  1027.         reg = r & VT_VALMASK;
  1028.         if (reg >= VT_CONST)
  1029.             error("internal compiler error");
  1030.         snprintf(buf, sizeof(buf), "(%%%s)",
  1031.                  get_tok_str(TOK_ASM_eax + reg, NULL));
  1032.         cstr_cat(add_str, buf);
  1033.     } else {
  1034.         /* register case */
  1035.         reg = r & VT_VALMASK;
  1036.         if (reg >= VT_CONST)
  1037.             error("internal compiler error");
  1038.  
  1039.         /* choose register operand size */
  1040.         if ((sv->type.t & VT_BTYPE) == VT_BYTE)
  1041.             size = 1;
  1042.         else if ((sv->type.t & VT_BTYPE) == VT_SHORT)
  1043.             size = 2;
  1044.         else
  1045.             size = 4;
  1046.         if (size == 1 && reg >= 4)
  1047.             size = 4;
  1048.  
  1049.         if (modifier == 'b') {
  1050.             if (reg >= 4)
  1051.                 error("cannot use byte register");
  1052.             size = 1;
  1053.         } else if (modifier == 'h') {
  1054.             if (reg >= 4)
  1055.                 error("cannot use byte register");
  1056.             size = -1;
  1057.         } else if (modifier == 'w') {
  1058.             size = 2;
  1059.         }
  1060.  
  1061.         switch(size) {
  1062.         case -1:
  1063.             reg = TOK_ASM_ah + reg;
  1064.             break;
  1065.         case 1:
  1066.             reg = TOK_ASM_al + reg;
  1067.             break;
  1068.         case 2:
  1069.             reg = TOK_ASM_ax + reg;
  1070.             break;
  1071.         default:
  1072.             reg = TOK_ASM_eax + reg;
  1073.             break;
  1074.         }
  1075.         snprintf(buf, sizeof(buf), "%%%s", get_tok_str(reg, NULL));
  1076.         cstr_cat(add_str, buf);
  1077.     }
  1078. }
  1079.  
  1080. /* generate prolog and epilog code for asm statment */
  1081. static void asm_gen_code(ASMOperand *operands, int nb_operands,
  1082.                          int nb_outputs, int is_output,
  1083.                          uint8_t *clobber_regs,
  1084.                          int out_reg)
  1085. {
  1086.     uint8_t regs_allocated[NB_ASM_REGS];
  1087.     ASMOperand *op;
  1088.     int i, reg;
  1089.     static uint8_t reg_saved[NB_SAVED_REGS] = { 3, 6, 7 };
  1090.  
  1091.     /* mark all used registers */
  1092.     memcpy(regs_allocated, clobber_regs, sizeof(regs_allocated));
  1093.     for(i = 0; i < nb_operands;i++) {
  1094.         op = &operands[i];
  1095.         if (op->reg >= 0)
  1096.             regs_allocated[op->reg] = 1;
  1097.     }
  1098.     if (!is_output) {
  1099.         /* generate reg save code */
  1100.         for(i = 0; i < NB_SAVED_REGS; i++) {
  1101.             reg = reg_saved[i];
  1102.             if (regs_allocated[reg])
  1103.                 g(0x50 + reg);
  1104.         }
  1105.  
  1106.         /* generate load code */
  1107.         for(i = 0; i < nb_operands; i++) {
  1108.             op = &operands[i];
  1109.             if (op->reg >= 0) {
  1110.                 if ((op->vt->r & VT_VALMASK) == VT_LLOCAL &&
  1111.                     op->is_memory) {
  1112.                     /* memory reference case (for both input and
  1113.                        output cases) */
  1114.                     SValue sv;
  1115.                     sv = *op->vt;
  1116.                     sv.r = (sv.r & ~VT_VALMASK) | VT_LOCAL;
  1117.                     load(op->reg, &sv);
  1118.                 } else if (i >= nb_outputs || op->is_rw) {
  1119.                     /* load value in register */
  1120.                     load(op->reg, op->vt);
  1121.                     if (op->is_llong) {
  1122.                         SValue sv;
  1123.                         sv = *op->vt;
  1124.                         sv.c.ul += 4;
  1125.                         load(TREG_EDX, &sv);
  1126.                     }
  1127.                 }
  1128.             }
  1129.         }
  1130.     } else {
  1131.         /* generate save code */
  1132.         for(i = 0 ; i < nb_outputs; i++) {
  1133.             op = &operands[i];
  1134.             if (op->reg >= 0) {
  1135.                 if ((op->vt->r & VT_VALMASK) == VT_LLOCAL) {
  1136.                     if (!op->is_memory) {
  1137.                         SValue sv;
  1138.                         sv = *op->vt;
  1139.                         sv.r = (sv.r & ~VT_VALMASK) | VT_LOCAL;
  1140.                         load(out_reg, &sv);
  1141.  
  1142.                         sv.r = (sv.r & ~VT_VALMASK) | out_reg;
  1143.                         store(op->reg, &sv);
  1144.                     }
  1145.                 } else {
  1146.                     store(op->reg, op->vt);
  1147.                     if (op->is_llong) {
  1148.                         SValue sv;
  1149.                         sv = *op->vt;
  1150.                         sv.c.ul += 4;
  1151.                         store(TREG_EDX, &sv);
  1152.                     }
  1153.                 }
  1154.             }
  1155.         }
  1156.         /* generate reg restore code */
  1157.         for(i = NB_SAVED_REGS - 1; i >= 0; i--) {
  1158.             reg = reg_saved[i];
  1159.             if (regs_allocated[reg])
  1160.                 g(0x58 + reg);
  1161.         }
  1162.     }
  1163. }
  1164.  
  1165. static void asm_clobber(uint8_t *clobber_regs, const char *str)
  1166. {
  1167.     int reg;
  1168.     TokenSym *ts;
  1169.  
  1170.     if (!strcmp(str, "memory") ||
  1171.         !strcmp(str, "cc"))
  1172.         return;
  1173.     ts = tok_alloc(str, strlen(str));
  1174.     reg = ts->tok;
  1175.     if (reg >= TOK_ASM_eax && reg <= TOK_ASM_edi) {
  1176.         reg -= TOK_ASM_eax;
  1177.     } else if (reg >= TOK_ASM_ax && reg <= TOK_ASM_di) {
  1178.         reg -= TOK_ASM_ax;
  1179.     } else {
  1180.         error("invalid clobber register '%s'", str);
  1181.     }
  1182.     clobber_regs[reg] = 1;
  1183. }
  1184.