Subversion Repositories Kolibri OS

Rev

Rev 647 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

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