Subversion Repositories Kolibri OS

Rev

Rev 647 | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 647 Rev 6429
Line 1... Line 1...
1
/*
1
/*
2
 *  i386 specific functions for TCC assembler
2
 *  i386 specific functions for TCC assembler
3
 * 
3
 *
4
 *  Copyright (c) 2001, 2002 Fabrice Bellard
4
 *  Copyright (c) 2001, 2002 Fabrice Bellard
-
 
5
 *  Copyright (c) 2009 Frédéric Feret (x86_64 support)
5
 *
6
 *
6
 * This library is free software; you can redistribute it and/or
7
 * This library is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU Lesser General Public
8
 * modify it under the terms of the GNU Lesser General Public
8
 * License as published by the Free Software Foundation; either
9
 * License as published by the Free Software Foundation; either
9
 * version 2 of the License, or (at your option) any later version.
10
 * version 2 of the License, or (at your option) any later version.
Line 16... Line 17...
16
 * You should have received a copy of the GNU Lesser General Public
17
 * 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
 * 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
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19
 */
20
 */
Line -... Line 21...
-
 
21
 
-
 
22
#include "tcc.h"
-
 
23
 
20
 
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
Line 21... Line -...
21
#define MAX_OPERANDS 3
-
 
22
 
-
 
23
typedef struct ASMInstr {
-
 
24
    uint16_t sym;
-
 
25
    uint16_t opcode;
30
#define TOK_ASM_alllast TOK_ASM_pxor
26
    uint16_t instr_type;
31
 
27
#define OPC_JMP       0x01  /* jmp operand */
32
#define OPC_JMP        0x01  /* jmp operand */
28
#define OPC_B         0x02  /* only used zith OPC_WL */
33
#define OPC_B          0x02  /* only used with OPC_WL */
29
#define OPC_WL        0x04  /* accepts w, l or no suffix */
34
#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 */
35
#define OPC_BWL        (OPC_B | OPC_WL) /* accepts b, w, l or no suffix */
31
#define OPC_REG       0x08 /* register is added to opcode */
36
#define OPC_REG        0x08 /* register is added to opcode */
Line 35... Line 40...
35
#define OPC_SHIFT     0x80 /* shift opcodes */
40
#define OPC_SHIFT      0x80 /* shift opcodes */
36
#define OPC_D16      0x0100 /* generate data16 prefix */
41
#define OPC_D16      0x0100 /* generate data16 prefix */
37
#define OPC_ARITH    0x0200 /* arithmetic opcodes */
42
#define OPC_ARITH    0x0200 /* arithmetic opcodes */
38
#define OPC_SHORTJMP 0x0400 /* short jmp operand */
43
#define OPC_SHORTJMP 0x0400 /* short jmp operand */
39
#define OPC_FARITH   0x0800 /* FPU arithmetic opcodes */
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
 
40
#define OPC_GROUP_SHIFT 13
53
#define OPC_GROUP_SHIFT 13
Line 41... Line 54...
41
 
54
 
42
/* in order to compress the operand type, we use specific operands and
55
/* in order to compress the operand type, we use specific operands and
-
 
56
   we or only with EA  */
43
   we or only with EA  */ 
57
enum {
44
#define OPT_REG8  0 /* warning: value is hardcoded from TOK_ASM_xxx */
58
    OPT_REG8=0, /* warning: value is hardcoded from TOK_ASM_xxx */
45
#define OPT_REG16 1 /* 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 */
46
#define OPT_REG32 2 /* warning: value is hardcoded from TOK_ASM_xxx */
63
#endif
47
#define OPT_MMX   3 /* warning: value is hardcoded from TOK_ASM_xxx */
64
    OPT_MMX,    /* warning: value is hardcoded from TOK_ASM_xxx */
48
#define OPT_SSE   4 /* warning: value is hardcoded from TOK_ASM_xxx */
65
    OPT_SSE,    /* warning: value is hardcoded from TOK_ASM_xxx */
49
#define OPT_CR    5 /* warning: value is hardcoded from TOK_ASM_xxx */
66
    OPT_CR,     /* warning: value is hardcoded from TOK_ASM_xxx */
50
#define OPT_TR    6 /* warning: value is hardcoded from TOK_ASM_xxx */
67
    OPT_TR,     /* warning: value is hardcoded from TOK_ASM_xxx */
51
#define OPT_DB    7 /* warning: value is hardcoded from TOK_ASM_xxx */
68
    OPT_DB,     /* warning: value is hardcoded from TOK_ASM_xxx */
52
#define OPT_SEG   8
69
    OPT_SEG,
53
#define OPT_ST    9
70
    OPT_ST,
54
#define OPT_IM8   10
71
    OPT_IM8,
55
#define OPT_IM8S  11
72
    OPT_IM8S,
56
#define OPT_IM16  12
73
    OPT_IM16,
-
 
74
    OPT_IM32,
-
 
75
#ifdef TCC_TARGET_X86_64
-
 
76
    OPT_IM64,
57
#define OPT_IM32  13
77
#endif
58
#define OPT_EAX   14 /* %al, %ax or %eax register */
78
    OPT_EAX,    /* %al, %ax, %eax or %rax register */
59
#define OPT_ST0   15 /* %st(0) register */
79
    OPT_ST0,    /* %st(0) register */
60
#define OPT_CL    16 /* %cl register */
80
    OPT_CL,     /* %cl register */
61
#define OPT_DX    17 /* %dx register */
81
    OPT_DX,     /* %dx register */
62
#define OPT_ADDR  18 /* OP_EA with only offset */
82
    OPT_ADDR,   /* OP_EA with only offset */
63
#define OPT_INDIR 19 /* *(expr) */
-
 
64
 
83
    OPT_INDIR,  /* *(expr) */
65
/* composite types */ 
84
    /* composite types */
66
#define OPT_COMPOSITE_FIRST   20
85
    OPT_COMPOSITE_FIRST,
67
#define OPT_IM       20 /* IM8 | IM16 | IM32 */
86
    OPT_IM,     /* IM8 | IM16 | IM32 | IM64 */
68
#define OPT_REG      21 /* REG8 | REG16 | REG32 */ 
87
    OPT_REG,    /* REG8 | REG16 | REG32 | REG64 */
-
 
88
    OPT_REGW,   /* REG16 | REG32 | REG64 */
-
 
89
    OPT_IMW,    /* IM16 | IM32 | IM64 */
69
#define OPT_REGW     22 /* REG16 | REG32 */
90
#ifdef TCC_TARGET_X86_64
70
#define OPT_IMW      23 /* IM16 | IM32 */ 
91
    OPT_IMNO64, /* IM16 | IM32 */
71
 
92
#endif
72
/* can be ored with any OPT_xxx */
93
    /* can be ored with any OPT_xxx */
73
#define OPT_EA    0x80
94
    OPT_EA = 0x80
74
 
-
 
75
    uint8_t nb_ops;
-
 
76
    uint8_t op_type[MAX_OPERANDS]; /* see OP_xxx */
-
 
Line 77... Line -...
77
} ASMInstr;
-
 
78
 
-
 
79
typedef struct Operand {
95
};
80
    uint32_t type;
96
 
81
#define OP_REG8   (1 << OPT_REG8)
97
#define OP_REG8   (1 << OPT_REG8)
82
#define OP_REG16  (1 << OPT_REG16)
98
#define OP_REG16  (1 << OPT_REG16)
83
#define OP_REG32  (1 << OPT_REG32)
99
#define OP_REG32  (1 << OPT_REG32)
Line 96... Line 112...
96
#define OP_ST0    (1 << OPT_ST0)
112
#define OP_ST0    (1 << OPT_ST0)
97
#define OP_CL     (1 << OPT_CL)
113
#define OP_CL     (1 << OPT_CL)
98
#define OP_DX     (1 << OPT_DX)
114
#define OP_DX     (1 << OPT_DX)
99
#define OP_ADDR   (1 << OPT_ADDR)
115
#define OP_ADDR   (1 << OPT_ADDR)
100
#define OP_INDIR  (1 << OPT_INDIR)
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
Line 101... Line 124...
101
 
124
 
102
#define OP_EA     0x40000000
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
103
#define OP_REG    (OP_REG8 | OP_REG16 | OP_REG32)
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 {
104
#define OP_IM     OP_IM32
149
    uint32_t type;
105
    int8_t  reg; /* register, -1 if none */
150
    int8_t  reg; /* register, -1 if none */
106
    int8_t  reg2; /* second register, -1 if none */
151
    int8_t  reg2; /* second register, -1 if none */
107
    uint8_t shift;
152
    uint8_t shift;
108
    ExprValue e;
153
    ExprValue e;
Line 109... Line 154...
109
} Operand;
154
} Operand;
-
 
155
 
110
 
156
static const uint8_t reg_to_size[9] = {
111
static const uint8_t reg_to_size[5] = {
157
/*
112
    [OP_REG8] = 0,
158
    [OP_REG8] = 0,
-
 
159
    [OP_REG16] = 1,
-
 
160
    [OP_REG32] = 2,
-
 
161
#ifdef TCC_TARGET_X86_64
-
 
162
    [OP_REG64] = 3,
-
 
163
#endif
113
    [OP_REG16] = 1,
164
*/
Line 114... Line -...
114
    [OP_REG32] = 2,
-
 
115
};
-
 
116
    
165
    0, 0, 1, 0, 2, 0, 0, 0, 3
Line 117... Line 166...
117
#define WORD_PREFIX_OPCODE 0x66
166
};
118
 
167
 
119
#define NB_TEST_OPCODES 30
168
#define NB_TEST_OPCODES 30
Line 149... Line 198...
149
 0x0e, /* ng */
198
 0x0e, /* ng */
150
 0x0f, /* nle */
199
 0x0f, /* nle */
151
 0x0f, /* g */
200
 0x0f, /* g */
152
};
201
};
Line -... Line 202...
-
 
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
};
153
 
211
 
154
static const ASMInstr asm_instrs[] = {
212
static const ASMInstr asm_instrs[] = {
155
#define ALT(x) x
213
#define ALT(x) x
156
#define DEF_ASM_OP0(name, opcode)
214
#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 },
215
#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 }},
216
#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 }},
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"
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 }},
221
#else
161
#include "i386-asm.h"
222
# include "i386-asm.h"
162
 
223
#endif
163
    /* last operation */
224
    /* last operation */
164
    { 0, },
225
    { 0, },
Line 165... Line 226...
165
};
226
};
Line 169... Line 230...
169
#define DEF_ASM_OP0(x, opcode) opcode,
230
#define DEF_ASM_OP0(x, opcode) opcode,
170
#define DEF_ASM_OP0L(name, opcode, group, instr_type)
231
#define DEF_ASM_OP0L(name, opcode, group, instr_type)
171
#define DEF_ASM_OP1(name, opcode, group, instr_type, op0)
232
#define DEF_ASM_OP1(name, opcode, group, instr_type, op0)
172
#define DEF_ASM_OP2(name, opcode, group, instr_type, op0, op1)
233
#define DEF_ASM_OP2(name, opcode, group, instr_type, op0, op1)
173
#define DEF_ASM_OP3(name, opcode, group, instr_type, op0, op1, op2)
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
174
#include "i386-asm.h"
238
# include "i386-asm.h"
-
 
239
#endif
175
};
240
};
Line 176... Line 241...
176
 
241
 
177
static inline int get_reg_shift(TCCState *s1)
242
static inline int get_reg_shift(TCCState *s1)
178
{
243
{
-
 
244
    int shift, v;
-
 
245
#ifdef I386_ASM_16
-
 
246
    if (s1->seg_size == 16)
179
    int shift, v;
247
        tcc_error("invalid effective address");
180
 
248
#endif
181
    v = asm_int_expr(s1);
249
    v = asm_int_expr(s1);
182
    switch(v) {
250
    switch(v) {
183
    case 1:
251
    case 1:
184
        shift = 0;
252
        shift = 0;
Line 200... Line 268...
200
    return shift;
268
    return shift;
201
}
269
}
Line 202... Line 270...
202
 
270
 
203
static int asm_parse_reg(void)
271
static int asm_parse_reg(void)
204
{
272
{
205
    int reg;
273
    int reg = 0;
206
    if (tok != '%')
274
    if (tok != '%')
207
        goto error_32;
275
        goto error_32;
208
    next();
276
    next();
209
    if (tok >= TOK_ASM_eax && tok <= TOK_ASM_edi) {
277
    if (tok >= TOK_ASM_eax && tok <= TOK_ASM_edi) {
-
 
278
        reg = tok - TOK_ASM_eax;
-
 
279
#ifdef TCC_TARGET_X86_64
210
        reg = tok - TOK_ASM_eax;
280
    } else if (tok >= TOK_ASM_rax && tok <= TOK_ASM_rdi) {
-
 
281
        reg = tok - TOK_ASM_rax;
-
 
282
#endif
-
 
283
#ifdef I386_ASM_16
211
        next();
284
    } else if (tok >= TOK_ASM_ax && tok <= TOK_ASM_di) {
-
 
285
        reg = tok - TOK_ASM_ax;
212
        return reg;
286
#endif
213
    } else {
287
    } else {
214
    error_32:
288
    error_32:
215
        expect("32 bit register");
-
 
216
        return 0;
289
        expect("register");
-
 
290
    }
-
 
291
    next();
217
    }
292
    return reg;
Line 218... Line 293...
218
}
293
}
219
 
294
 
220
static void parse_operand(TCCState *s1, Operand *op)
295
static void parse_operand(TCCState *s1, Operand *op)
Line 233... Line 308...
233
        next();
308
        next();
234
        if (tok >= TOK_ASM_al && tok <= TOK_ASM_db7) {
309
        if (tok >= TOK_ASM_al && tok <= TOK_ASM_db7) {
235
            reg = tok - TOK_ASM_al;
310
            reg = tok - TOK_ASM_al;
236
            op->type = 1 << (reg >> 3); /* WARNING: do not change constant order */
311
            op->type = 1 << (reg >> 3); /* WARNING: do not change constant order */
237
            op->reg = reg & 7;
312
            op->reg = reg & 7;
238
            if ((op->type & OP_REG) && op->reg == TREG_EAX)
313
            if ((op->type & OP_REG) && op->reg == TREG_XAX)
239
                op->type |= OP_EAX;
314
                op->type |= OP_EAX;
240
            else if (op->type == OP_REG8 && op->reg == TREG_ECX)
315
            else if (op->type == OP_REG8 && op->reg == TREG_XCX)
241
                op->type |= OP_CL;
316
                op->type |= OP_CL;
242
            else if (op->type == OP_REG16 && op->reg == TREG_EDX)
317
            else if (op->type == OP_REG16 && op->reg == TREG_XDX)
243
                op->type |= OP_DX;
318
                op->type |= OP_DX;
244
        } else if (tok >= TOK_ASM_dr0 && tok <= TOK_ASM_dr7) {
319
        } else if (tok >= TOK_ASM_dr0 && tok <= TOK_ASM_dr7) {
245
            op->type = OP_DB;
320
            op->type = OP_DB;
246
            op->reg = tok - TOK_ASM_dr0;
321
            op->reg = tok - TOK_ASM_dr0;
247
        } else if (tok >= TOK_ASM_es && tok <= TOK_ASM_gs) {
322
        } else if (tok >= TOK_ASM_es && tok <= TOK_ASM_gs) {
Line 253... Line 328...
253
            next();
328
            next();
254
            if (tok == '(') {
329
            if (tok == '(') {
255
                next();
330
                next();
256
                if (tok != TOK_PPNUM)
331
                if (tok != TOK_PPNUM)
257
                    goto reg_error;
332
                    goto reg_error;
258
                p = tokc.cstr->data;
333
                p = tokc.str.data;
259
                reg = p[0] - '0';
334
                reg = p[0] - '0';
260
                if ((unsigned)reg >= 8 || p[1] != '\0')
335
                if ((unsigned)reg >= 8 || p[1] != '\0')
261
                    goto reg_error;
336
                    goto reg_error;
262
                op->reg = reg;
337
                op->reg = reg;
263
                next();
338
                next();
Line 266... Line 341...
266
            if (op->reg == 0)
341
            if (op->reg == 0)
267
                op->type |= OP_ST0;
342
                op->type |= OP_ST0;
268
            goto no_skip;
343
            goto no_skip;
269
        } else {
344
        } else {
270
        reg_error:
345
        reg_error:
271
            error("unknown register");
346
            tcc_error("unknown register");
272
        }
347
        }
273
        next();
348
        next();
274
    no_skip: ;
349
    no_skip: ;
275
    } else if (tok == '$') {
350
    } else if (tok == '$') {
276
        /* constant value */
351
        /* constant value */
277
        next();
352
        next();
278
        asm_expr(s1, &e);
353
        asm_expr(s1, &e);
279
        op->type = OP_IM32;
354
        op->type = OP_IM;
280
        op->e.v = e.v;
355
        op->e.v = e.v;
281
        op->e.sym = e.sym;
356
        op->e.sym = e.sym;
282
        if (!op->e.sym) {
357
        if (!op->e.sym) {
283
            if (op->e.v == (uint8_t)op->e.v)
358
            if (op->e.v == (uint8_t)op->e.v)
284
                op->type |= OP_IM8;
359
                op->type |= OP_IM8;
285
            if (op->e.v == (int8_t)op->e.v)
360
            if (op->e.v == (int8_t)op->e.v)
286
                op->type |= OP_IM8S;
361
                op->type |= OP_IM8S;
287
            if (op->e.v == (uint16_t)op->e.v)
362
            if (op->e.v == (uint16_t)op->e.v)
288
                op->type |= OP_IM16;
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
289
        }
368
        }
290
    } else {
369
    } else {
291
        /* address(reg,reg2,shift) with all variants */
370
        /* address(reg,reg2,shift) with all variants */
292
        op->type = OP_EA;
371
        op->type = OP_EA;
293
        op->reg = -1;
372
        op->reg = -1;
Line 296... Line 375...
296
        if (tok != '(') {
375
        if (tok != '(') {
297
            asm_expr(s1, &e);
376
            asm_expr(s1, &e);
298
            op->e.v = e.v;
377
            op->e.v = e.v;
299
            op->e.sym = e.sym;
378
            op->e.sym = e.sym;
300
        } else {
379
        } else {
-
 
380
            next();
-
 
381
            if (tok == '%') {
-
 
382
                unget_tok('(');
301
            op->e.v = 0;
383
                op->e.v = 0;
302
            op->e.sym = NULL;
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
            }
303
        }
394
        }
304
        if (tok == '(') {
395
        if (tok == '(') {
305
            next();
396
            next();
306
            if (tok != ',') {
397
            if (tok != ',') {
307
                op->reg = asm_parse_reg();
398
                op->reg = asm_parse_reg();
Line 309... Line 400...
309
            if (tok == ',') {
400
            if (tok == ',') {
310
                next();
401
                next();
311
                if (tok != ',') {
402
                if (tok != ',') {
312
                    op->reg2 = asm_parse_reg();
403
                    op->reg2 = asm_parse_reg();
313
                } 
404
                }
-
 
405
                if (tok == ',') {
314
                skip(',');
406
                    next();
315
                op->shift = get_reg_shift(s1);
407
                    op->shift = get_reg_shift(s1);
316
            }
408
                }
-
 
409
            }
317
            skip(')');
410
            skip(')');
318
        }
411
        }
319
        if (op->reg == -1 && op->reg2 == -1)
412
        if (op->reg == -1 && op->reg2 == -1)
320
            op->type |= OP_ADDR;
413
            op->type |= OP_ADDR;
321
    }
414
    }
322
    op->type |= indir;
415
    op->type |= indir;
323
}
416
}
Line 324... Line 417...
324
 
417
 
325
/* XXX: unify with C code output ? */
418
/* XXX: unify with C code output ? */
326
static void gen_expr32(ExprValue *pe)
419
ST_FUNC void gen_expr32(ExprValue *pe)
-
 
420
{
-
 
421
    gen_addr32(pe->sym ? VT_SYM : 0, pe->sym, pe->v);
-
 
422
}
327
{
423
 
328
    if (pe->sym)
424
#ifdef TCC_TARGET_X86_64
-
 
425
static void gen_expr64(ExprValue *pe)
329
        greloc(cur_text_section, pe->sym, ind, R_386_32);
426
{
330
    gen_le32(pe->v);
427
    gen_addr64(pe->sym ? VT_SYM : 0, pe->sym, pe->v);
-
 
428
}
Line 331... Line 429...
331
}
429
#endif
332
 
430
 
333
/* XXX: unify with C code output ? */
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
}
334
static void gen_disp32(ExprValue *pe)
457
static void gen_disp16(ExprValue *pe)
335
{
458
{
336
    Sym *sym;
459
    Sym *sym;
337
    sym = pe->sym;
460
    sym = pe->sym;
338
    if (sym) {
461
    if (sym) {
339
        if (sym->r == cur_text_section->sh_num) {
462
        if (sym->r == cur_text_section->sh_num) {
340
            /* same section: we can output an absolute value. Note
463
            /* same section: we can output an absolute value. Note
341
               that the TCC compiler behaves differently here because
464
               that the TCC compiler behaves differently here because
342
               it always outputs a relocation to ease (future) code
465
               it always outputs a relocation to ease (future) code
343
               elimination in the linker */
466
               elimination in the linker */
344
            gen_le32(pe->v + (long)sym->next - ind - 4);
467
            gen_le16(pe->v + sym->jnext - ind - 2);
345
        } else {
468
        } else {
346
            greloc(cur_text_section, sym, ind, R_386_PC32);
469
            greloc(cur_text_section, sym, ind, R_386_PC16);
347
            gen_le32(pe->v - 4);
470
            gen_le16(pe->v - 2);
348
        }
471
        }
349
    } else {
472
    } else {
350
        /* put an empty PC32 relocation */
473
        /* put an empty PC32 relocation */
351
        put_elf_reloc(symtab_section, cur_text_section, 
474
        put_elf_reloc(symtab_section, cur_text_section,
352
                      ind, R_386_PC32, 0);
475
                      ind, R_386_PC16, 0);
353
        gen_le32(pe->v - 4);
476
        gen_le16(pe->v - 2);
354
    }
-
 
355
}
-
 
356
 
-
 
357
 
-
 
358
static void gen_le16(int v)
477
    }
359
{
-
 
360
    g(v);
-
 
Line 361... Line 478...
361
    g(v >> 8);
478
}
362
}
479
#endif
363
 
480
 
364
/* generate the modrm operand */
481
/* generate the modrm operand */
Line 365... Line 482...
365
static inline void asm_modrm(int reg, Operand *op)
482
static inline void asm_modrm(int reg, Operand *op)
366
{
483
{
367
    int mod, reg1, reg2, sib_reg1;
484
    int mod, reg1, reg2, sib_reg1;
368
 
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));
369
    if (op->type & (OP_REG | OP_MMX | OP_SSE)) {
493
            gen_expr16(&op->e);
370
        g(0xc0 + (reg << 3) + op->reg);
494
        } else if (tcc_state->seg_size == 32)
-
 
495
#endif
371
    } else if (op->reg == -1 && op->reg2 == -1) {
496
        {
372
        /* displacement only */
497
            g(0x05 + (reg << 3));
373
        g(0x05 + (reg << 3));
498
            gen_expr32(&op->e);
374
        gen_expr32(&op->e);
499
        }
375
    } else {
500
    } else {
Line 387... Line 512...
387
        }
512
        }
388
        /* compute if sib byte needed */
513
        /* compute if sib byte needed */
389
        reg1 = op->reg;
514
        reg1 = op->reg;
390
        if (op->reg2 != -1)
515
        if (op->reg2 != -1)
391
            reg1 = 4;
516
            reg1 = 4;
-
 
517
#ifdef I386_ASM_16
-
 
518
        if (tcc_state->seg_size == 32) {
-
 
519
#endif
392
        g(mod + (reg << 3) + reg1);
520
        g(mod + (reg << 3) + reg1);
393
        if (reg1 == 4) {
521
        if (reg1 == 4) {
394
            /* add sib byte */
522
            /* add sib byte */
395
            reg2 = op->reg2;
523
            reg2 = op->reg2;
396
            if (reg2 == -1)
524
            if (reg2 == -1)
397
                reg2 = 4; /* indicate no index */
525
                reg2 = 4; /* indicate no index */
398
            g((op->shift << 6) + (reg2 << 3) + sib_reg1);
526
            g((op->shift << 6) + (reg2 << 3) + sib_reg1);
399
        }
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");
400
 
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
401
        /* add offset */
565
        /* add offset */
402
        if (mod == 0x40) {
566
        if (mod == 0x40) {
403
            g(op->e.v);
567
            g(op->e.v);
404
        } else if (mod == 0x80 || op->reg == -1) {
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
405
            gen_expr32(&op->e);
574
                gen_expr32(&op->e);
406
        }
575
        }
407
    }
576
    }
408
}
577
}
Line 409... Line 578...
409
 
578
 
410
static void asm_opcode(TCCState *s1, int opcode)
579
ST_FUNC void asm_opcode(TCCState *s1, int opcode)
411
{
580
{
412
    const ASMInstr *pa;
581
    const ASMInstr *pa;
413
    int i, modrm_index, reg, v, op1, is_short_jmp;
582
    int i, modrm_index, reg, v, op1, is_short_jmp, seg_prefix;
414
    int nb_ops, s, ss;
583
    int nb_ops, s;
415
    Operand ops[MAX_OPERANDS], *pop;
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)
Line 416... Line 593...
416
    int op_type[3]; /* decoded op type */
593
        unget_tok(';');
417
 
594
 
418
    /* get operands */
595
    /* get operands */
-
 
596
    pop = ops;
419
    pop = ops;
597
    nb_ops = 0;
420
    nb_ops = 0;
598
    seg_prefix = 0;
421
    for(;;) {
599
    for(;;) {
422
        if (tok == ';' || tok == TOK_LINEFEED)
600
        if (tok == ';' || tok == TOK_LINEFEED)
423
            break;
601
            break;
424
        if (nb_ops >= MAX_OPERANDS) {
602
        if (nb_ops >= MAX_OPERANDS) {
425
            error("incorrect number of 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
           }
426
        }
616
#endif
427
        parse_operand(s1, pop);
617
        }
428
        pop++;
618
        pop++;
429
        nb_ops++;
619
        nb_ops++;
430
        if (tok != ',')
620
        if (tok != ',')
Line 442... Line 632...
442
        if (pa->instr_type & OPC_FARITH) {
632
        if (pa->instr_type & OPC_FARITH) {
443
            v = opcode - pa->sym;
633
            v = opcode - pa->sym;
444
            if (!((unsigned)v < 8 * 6 && (v % 6) == 0))
634
            if (!((unsigned)v < 8 * 6 && (v % 6) == 0))
445
                continue;
635
                continue;
446
        } else if (pa->instr_type & OPC_ARITH) {
636
        } else if (pa->instr_type & OPC_ARITH) {
447
            if (!(opcode >= pa->sym && opcode < pa->sym + 8 * 4))
637
            if (!(opcode >= pa->sym && opcode < pa->sym + 8*NBWLX))
448
                continue;
638
                continue;
449
            goto compute_size;
639
            s = (opcode - pa->sym) % NBWLX;
450
        } else if (pa->instr_type & OPC_SHIFT) {
640
        } else if (pa->instr_type & OPC_SHIFT) {
451
            if (!(opcode >= pa->sym && opcode < pa->sym + 7 * 4))
641
            if (!(opcode >= pa->sym && opcode < pa->sym + 7*NBWLX))
452
                continue;
642
                continue;
453
            goto compute_size;
643
            s = (opcode - pa->sym) % NBWLX;
454
        } else if (pa->instr_type & OPC_TEST) {
644
        } else if (pa->instr_type & OPC_TEST) {
455
            if (!(opcode >= pa->sym && opcode < pa->sym + NB_TEST_OPCODES))
645
            if (!(opcode >= pa->sym && opcode < pa->sym + NB_TEST_OPCODES))
456
                continue;
646
                continue;
457
        } else if (pa->instr_type & OPC_B) {
647
        } else if (pa->instr_type & OPC_B) {
458
            if (!(opcode >= pa->sym && opcode <= pa->sym + 3))
648
            if (!(opcode >= pa->sym && opcode < pa->sym + NBWLX))
459
                continue;
649
                continue;
460
        compute_size:
-
 
461
            s = (opcode - pa->sym) & 3;
650
            s = opcode - pa->sym;
462
        } else if (pa->instr_type & OPC_WL) {
651
        } else if (pa->instr_type & OPC_WLX) {
463
            if (!(opcode >= pa->sym && opcode <= pa->sym + 2))
652
            if (!(opcode >= pa->sym && opcode < pa->sym + NBWLX-1))
464
                continue;
653
                continue;
465
            s = opcode - pa->sym + 1;
654
            s = opcode - pa->sym + 1;
466
        } else {
655
        } else {
467
            if (pa->sym != opcode)
656
            if (pa->sym != opcode)
468
                continue;
657
                continue;
Line 474... Line 663...
474
            int op1, op2;
663
            int op1, op2;
475
            op1 = pa->op_type[i];
664
            op1 = pa->op_type[i];
476
            op2 = op1 & 0x1f;
665
            op2 = op1 & 0x1f;
477
            switch(op2) {
666
            switch(op2) {
478
            case OPT_IM:
667
            case OPT_IM:
479
                v = OP_IM8 | OP_IM16 | OP_IM32;
668
                v = OP_IM8 | OP_IM16 | OP_IM32 | OP_IM64;
480
                break;
669
                break;
481
            case OPT_REG:
670
            case OPT_REG:
482
                v = OP_REG8 | OP_REG16 | OP_REG32;
671
                v = OP_REG8 | OP_REG16 | OP_REG32 | OP_REG64;
483
                break;
672
                break;
484
            case OPT_REGW:
673
            case OPT_REGW:
485
                v = OP_REG16 | OP_REG32;
674
                v = OP_REG16 | OP_REG32 | OP_REG64;
486
                break;
675
                break;
487
            case OPT_IMW:
676
            case OPT_IMW:
-
 
677
                v = OP_IM16 | OP_IM32 | OP_IM64;
-
 
678
                break;
-
 
679
#ifdef TCC_TARGET_X86_64
-
 
680
            case OPT_IMNO64:
488
                v = OP_IM16 | OP_IM32;
681
                v = OP_IM16 | OP_IM32;
489
                break;
682
                break;
-
 
683
#endif
490
            default:
684
            default:
491
                v = 1 << op2;
685
                v = 1 << op2;
492
                break;
686
                break;
493
            }
687
            }
494
            if (op1 & OPT_EA)
688
            if (op1 & OPT_EA)
Line 500... Line 694...
500
        /* all is matching ! */
694
        /* all is matching ! */
501
        break;
695
        break;
502
    next: ;
696
    next: ;
503
    }
697
    }
504
    if (pa->sym == 0) {
698
    if (pa->sym == 0) {
505
        if (opcode >= TOK_ASM_pusha && opcode <= TOK_ASM_emms) {
699
        if (opcode >= TOK_ASM_first && opcode <= TOK_ASM_last) {
506
            int b;
700
            int b;
507
            b = op0_codes[opcode - TOK_ASM_pusha];
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
508
            if (b & 0xff00) 
715
            if (b & 0xff00) 
509
                g(b >> 8);
716
                g(b >> 8);
510
            g(b);
717
            g(b);
511
            return;
718
            return;
-
 
719
        } else if (opcode <= TOK_ASM_alllast) {
-
 
720
            tcc_error("bad operand with opcode '%s'",
-
 
721
                  get_tok_str(opcode, NULL));
512
        } else {
722
        } else {
513
            error("unknown opcode '%s'", 
723
            tcc_error("unknown opcode '%s'",
514
                  get_tok_str(opcode, NULL));
724
                  get_tok_str(opcode, NULL));
515
        }
725
        }
516
    }
726
    }
517
    /* if the size is unknown, then evaluate it (OPC_B or OPC_WL case) */
727
    /* if the size is unknown, then evaluate it (OPC_B or OPC_WL case) */
518
    if (s == 3) {
728
    if (s == NBWLX-1) {
519
        for(i = 0; s == 3 && i < nb_ops; i++) {
729
        for(i = 0; s == NBWLX-1 && i < nb_ops; i++) {
520
            if ((ops[i].type & OP_REG) && !(op_type[i] & (OP_CL | OP_DX)))
730
            if ((ops[i].type & OP_REG) && !(op_type[i] & (OP_CL | OP_DX)))
521
                s = reg_to_size[ops[i].type & OP_REG];
731
                s = reg_to_size[ops[i].type & OP_REG];
522
        }
732
        }
523
        if (s == 3) {
733
        if (s == NBWLX-1) {
524
            if ((opcode == TOK_ASM_push || opcode == TOK_ASM_pop) && 
734
            if ((opcode == TOK_ASM_push || opcode == TOK_ASM_pop) &&
525
                (ops[0].type & (OP_SEG | OP_IM8S | OP_IM32)))
735
                (ops[0].type & (OP_SEG | OP_IM8S | OP_IM32 | OP_IM64)))
526
                s = 2;
736
                s = 2;
527
            else
737
            else
528
                error("cannot infer opcode suffix");
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;
529
        }
761
        }
530
    }
762
    }
Line -... Line 763...
-
 
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;
531
 
772
#else
532
    /* generate data16 prefix if needed */
-
 
533
    ss = s;
773
    /* generate data16 prefix if needed */
534
    if (s == 1 || (pa->instr_type & OPC_D16))
774
    if (s == 1 || (pa->instr_type & OPC_D16))
-
 
775
        g(0x66);
535
        g(WORD_PREFIX_OPCODE);
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)
536
    else if (s == 2)
780
            || !(ops[0].type & OP_REG64))
-
 
781
            g(0x48);
-
 
782
    }
-
 
783
#endif
-
 
784
#endif
537
        s = 1;
785
 
538
    /* now generates the operation */
786
    /* now generates the operation */
539
    if (pa->instr_type & OPC_FWAIT)
787
    if (pa->instr_type & OPC_FWAIT)
-
 
788
        g(0x9b);
-
 
789
    if (seg_prefix)
Line 540... Line 790...
540
        g(0x9b);
790
        g(seg_prefix);
541
 
791
 
542
    v = pa->opcode;
792
    v = pa->opcode;
543
    if (v == 0x69 || v == 0x69) {
793
    if ((v == 0x69 || v == 0x6b) && nb_ops == 2) {
544
        /* kludge for imul $im, %reg */
794
        /* kludge for imul $im, %reg */
-
 
795
        nb_ops = 3;
545
        nb_ops = 3;
796
        ops[2] = ops[1];
546
        ops[2] = ops[1];
797
        op_type[2] = op_type[1];
547
    } else if (v == 0xcd && ops[0].e.v == 3 && !ops[0].e.sym) {
798
    } else if (v == 0xcd && ops[0].e.v == 3 && !ops[0].e.sym) {
548
        v--; /* int $3 case */
799
        v--; /* int $3 case */
549
        nb_ops = 0;
800
        nb_ops = 0;
Line 555... Line 806...
555
            v += ops[0].reg << 3;
806
            v += ops[0].reg << 3;
556
        }
807
        }
557
        nb_ops = 0;
808
        nb_ops = 0;
558
    } else if (v <= 0x05) {
809
    } else if (v <= 0x05) {
559
        /* arith case */
810
        /* arith case */
560
        v += ((opcode - TOK_ASM_addb) >> 2) << 3;
811
        v += ((opcode - TOK_ASM_addb) / NBWLX) << 3;
561
    } else if ((pa->instr_type & (OPC_FARITH | OPC_MODRM)) == OPC_FARITH) {
812
    } else if ((pa->instr_type & (OPC_FARITH | OPC_MODRM)) == OPC_FARITH) {
562
        /* fpu arith case */
813
        /* fpu arith case */
563
        v += ((opcode - pa->sym) / 6) << 3;
814
        v += ((opcode - pa->sym) / 6) << 3;
564
    }
815
    }
565
    if (pa->instr_type & OPC_REG) {
816
    if (pa->instr_type & OPC_REG) {
Line 572... Line 823...
572
        /* mov $im, %reg case */
823
        /* mov $im, %reg case */
573
        if (pa->opcode == 0xb0 && s >= 1)
824
        if (pa->opcode == 0xb0 && s >= 1)
574
            v += 7;
825
            v += 7;
575
    }
826
    }
576
    if (pa->instr_type & OPC_B)
827
    if (pa->instr_type & OPC_B)
577
        v += s;
828
        v += s >= 1;
578
    if (pa->instr_type & OPC_TEST)
829
    if (pa->instr_type & OPC_TEST)
579
        v += test_bits[opcode - pa->sym]; 
830
        v += test_bits[opcode - pa->sym];
580
    if (pa->instr_type & OPC_SHORTJMP) {
831
    if (pa->instr_type & OPC_SHORTJMP) {
581
        Sym *sym;
832
        Sym *sym;
582
        int jmp_disp;
833
        int jmp_disp;
Line 585... Line 836...
585
        sym = ops[0].e.sym;
836
        sym = ops[0].e.sym;
586
        if (!sym)
837
        if (!sym)
587
            goto no_short_jump;
838
            goto no_short_jump;
588
        if (sym->r != cur_text_section->sh_num)
839
        if (sym->r != cur_text_section->sh_num)
589
            goto no_short_jump;
840
            goto no_short_jump;
590
        jmp_disp = ops[0].e.v + (long)sym->next - ind - 2;
841
        jmp_disp = ops[0].e.v + sym->jnext - ind - 2;
591
        if (jmp_disp == (int8_t)jmp_disp) {
842
        if (jmp_disp == (int8_t)jmp_disp) {
592
            /* OK to generate jump */
843
            /* OK to generate jump */
593
            is_short_jmp = 1;
844
            is_short_jmp = 1;
594
            ops[0].e.v = jmp_disp;
845
            ops[0].e.v = jmp_disp;
595
        } else {
846
        } else {
Line 600... Line 851...
600
                if (v == 0xeb)
851
                if (v == 0xeb)
601
                    v = 0xe9;
852
                    v = 0xe9;
602
                else 
853
                else
603
                    v += 0x0f10;
854
                    v += 0x0f10;
604
            } else {
855
            } else {
605
                error("invalid displacement");
856
                tcc_error("invalid displacement");
606
            }
857
            }
607
        }
858
        }
608
    }
859
    }
609
    op1 = v >> 8;
860
    op1 = v >> 8;
610
    if (op1)
861
    if (op1)
Line 612... Line 863...
612
    g(v);
863
    g(v);
Line 613... Line 864...
613
        
864
 
614
    /* search which operand will used for modrm */
865
    /* search which operand will used for modrm */
615
    modrm_index = 0;
866
    modrm_index = 0;
616
    if (pa->instr_type & OPC_SHIFT) {
867
    if (pa->instr_type & OPC_SHIFT) {
617
        reg = (opcode - pa->sym) >> 2; 
868
        reg = (opcode - pa->sym) / NBWLX;
618
        if (reg == 6)
869
        if (reg == 6)
619
            reg = 7;
870
            reg = 7;
620
    } else if (pa->instr_type & OPC_ARITH) {
871
    } else if (pa->instr_type & OPC_ARITH) {
621
        reg = (opcode - pa->sym) >> 2;
872
        reg = (opcode - pa->sym) / NBWLX;
622
    } else if (pa->instr_type & OPC_FARITH) {
873
    } else if (pa->instr_type & OPC_FARITH) {
623
        reg = (opcode - pa->sym) / 6;
874
        reg = (opcode - pa->sym) / 6;
624
    } else {
875
    } else {
625
        reg = (pa->instr_type >> OPC_GROUP_SHIFT) & 7;
876
        reg = (pa->instr_type >> OPC_GROUP_SHIFT) & 7;
Line 634... Line 885...
634
        for(i = 0;i < nb_ops; i++) {
885
        for(i = 0;i < nb_ops; i++) {
635
            if (op_type[i] & (OP_REG | OP_MMX | OP_SSE | OP_INDIR))
886
            if (op_type[i] & (OP_REG | OP_MMX | OP_SSE | OP_INDIR))
636
                goto modrm_found;
887
                goto modrm_found;
637
        }
888
        }
638
#ifdef ASM_DEBUG
889
#ifdef ASM_DEBUG
639
        error("bad op table");
890
        tcc_error("bad op table");
640
#endif      
891
#endif
641
    modrm_found:
892
    modrm_found:
642
        modrm_index = i;
893
        modrm_index = i;
643
        /* if a register is used in another operand then it is
894
        /* if a register is used in another operand then it is
644
           used instead of group */
895
           used instead of group */
Line 653... Line 904...
653
 
904
 
654
        asm_modrm(reg, &ops[modrm_index]);
905
        asm_modrm(reg, &ops[modrm_index]);
Line 655... Line 906...
655
    }
906
    }
-
 
907
 
656
 
908
    /* emit constants */
657
    /* 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);
658
    if (pa->opcode == 0x9a || pa->opcode == 0xea) {
915
        else
659
        /* ljmp or lcall kludge */
916
#endif
660
        gen_expr32(&ops[1].e);
917
            gen_expr32(&ops[1].e);
661
        if (ops[0].e.sym)
918
        if (ops[0].e.sym)
662
            error("cannot relocate");
919
            tcc_error("cannot relocate");
-
 
920
        gen_le16(ops[0].e.v);
-
 
921
        return;
663
        gen_le16(ops[0].e.v);
922
    }
664
    } else {
923
#endif
665
        for(i = 0;i < nb_ops; i++) {
924
    for(i = 0;i < nb_ops; i++) {
666
            v = op_type[i];
925
        v = op_type[i];
667
            if (v & (OP_IM8 | OP_IM16 | OP_IM32 | OP_IM8S | OP_ADDR)) {
926
        if (v & (OP_IM8 | OP_IM16 | OP_IM32 | OP_IM64 | OP_IM8S | OP_ADDR)) {
668
                /* if multiple sizes are given it means we must look
927
            /* if multiple sizes are given it means we must look
669
                   at the op size */
-
 
670
                if (v == (OP_IM8 | OP_IM16 | OP_IM32) ||
928
               at the op size */
671
                    v == (OP_IM16 | OP_IM32)) {
929
            if ((v | OP_IM8 | OP_IM64) == (OP_IM8 | OP_IM16 | OP_IM32 | OP_IM64)) {
672
                    if (ss == 0)
930
                if (s == 0)
673
                        v = OP_IM8;
931
                    v = OP_IM8;
674
                    else if (ss == 1)
932
                else if (s == 1)
675
                        v = OP_IM16;
933
                    v = OP_IM16;
-
 
934
                else if (s == 2 || (v & OP_IM64) == 0)
-
 
935
                    v = OP_IM32;
676
                    else
936
                else
677
                        v = OP_IM32;
937
                    v = OP_IM64;
678
                }
938
            }
679
                if (v & (OP_IM8 | OP_IM8S)) {
939
            if (v & (OP_IM8 | OP_IM8S)) {
680
                    if (ops[i].e.sym)
940
                if (ops[i].e.sym)
681
                        goto error_relocate;
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);
682
                    g(ops[i].e.v);
947
                else
683
                } else if (v & OP_IM16) {
948
#endif
684
                    if (ops[i].e.sym) {
949
                if (ops[i].e.sym)
685
                    error_relocate:
950
                error_relocate:
686
                        error("cannot relocate");
951
                    tcc_error("cannot relocate");
687
                    }
952
                else
688
                    gen_le16(ops[i].e.v);
953
                    gen_le16(ops[i].e.v);
689
                } else {
954
            } else {
690
                    if (pa->instr_type & (OPC_JMP | OPC_SHORTJMP)) {
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)
691
                        if (is_short_jmp)
960
                        gen_disp16(&ops[i].e);
692
                            g(ops[i].e.v);
961
#endif
693
                        else
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);
694
                            gen_disp32(&ops[i].e);
973
                    else
695
                    } else {
974
#endif
696
                        gen_expr32(&ops[i].e);
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)) {
697
                    }
988
                /* jmp $r */
-
 
989
                g(0xE0 + ops[i].reg);
698
                }
990
            }
699
            }
991
#endif
-
 
992
        }
-
 
993
    }
-
 
994
#ifdef I386_ASM_16
700
        }
995
    a32 = o32 = 0;
Line 701... Line -...
701
    }
-
 
702
}
-
 
703
 
-
 
704
#define NB_SAVED_REGS 3
996
#endif
705
#define NB_ASM_REGS 8
997
}
706
 
998
 
707
/* return the constraint priority (we allocate first the lowest
999
/* return the constraint priority (we allocate first the lowest
708
   numbered constraints) */
1000
   numbered constraints) */
Line 742... Line 1034...
742
        case 'm':
1034
        case 'm':
743
        case 'g':
1035
        case 'g':
744
            pr = 4;
1036
            pr = 4;
745
            break;
1037
            break;
746
        default:
1038
        default:
747
            error("unknown constraint '%c'", c);
1039
            tcc_error("unknown constraint '%c'", c);
748
            pr = 0;
1040
            pr = 0;
749
        }
1041
        }
750
        if (pr > priority)
1042
        if (pr > priority)
751
            priority = pr;
1043
            priority = pr;
752
    }
1044
    }
Line 763... Line 1055...
763
#define REG_OUT_MASK 0x01
1055
#define REG_OUT_MASK 0x01
764
#define REG_IN_MASK  0x02
1056
#define REG_IN_MASK  0x02
Line 765... Line 1057...
765
 
1057
 
Line 766... Line 1058...
766
#define is_reg_allocated(reg) (regs_allocated[reg] & reg_mask)
1058
#define is_reg_allocated(reg) (regs_allocated[reg] & reg_mask)
767
 
1059
 
768
static void asm_compute_constraints(ASMOperand *operands, 
1060
ST_FUNC void asm_compute_constraints(ASMOperand *operands,
769
                                    int nb_operands, int nb_outputs, 
1061
                                    int nb_operands, int nb_outputs,
770
                                    const uint8_t *clobber_regs,
1062
                                    const uint8_t *clobber_regs,
771
                                    int *pout_reg)
1063
                                    int *pout_reg)
Line 793... Line 1085...
793
        str = skip_constraint_modifiers(str);
1085
        str = skip_constraint_modifiers(str);
794
        if (isnum(*str) || *str == '[') {
1086
        if (isnum(*str) || *str == '[') {
795
            /* this is a reference to another constraint */
1087
            /* this is a reference to another constraint */
796
            k = find_constraint(operands, nb_operands, str, NULL);
1088
            k = find_constraint(operands, nb_operands, str, NULL);
797
            if ((unsigned)k >= i || i < nb_outputs)
1089
            if ((unsigned)k >= i || i < nb_outputs)
798
                error("invalid reference in constraint %d ('%s')",
1090
                tcc_error("invalid reference in constraint %d ('%s')",
799
                      i, str);
1091
                      i, str);
800
            op->ref_index = k;
1092
            op->ref_index = k;
801
            if (operands[k].input_index >= 0)
1093
            if (operands[k].input_index >= 0)
802
                error("cannot reference twice the same operand");
1094
                tcc_error("cannot reference twice the same operand");
803
            operands[k].input_index = i;
1095
            operands[k].input_index = i;
804
            op->priority = 5;
1096
            op->priority = 5;
805
        } else {
1097
        } else {
806
            op->priority = constraint_priority(str);
1098
            op->priority = constraint_priority(str);
807
        }
1099
        }
Line 857... Line 1149...
857
        case '+':
1149
        case '+':
858
            op->is_rw = 1;
1150
            op->is_rw = 1;
859
            /* FALL THRU */
1151
            /* FALL THRU */
860
        case '&':
1152
        case '&':
861
            if (j >= nb_outputs)
1153
            if (j >= nb_outputs)
862
                error("'%c' modifier can only be applied to outputs", c);
1154
                tcc_error("'%c' modifier can only be applied to outputs", c);
863
            reg_mask = REG_IN_MASK | REG_OUT_MASK;
1155
            reg_mask = REG_IN_MASK | REG_OUT_MASK;
864
            goto try_next;
1156
            goto try_next;
865
        case 'A':
1157
        case 'A':
866
            /* allocate both eax and edx */
1158
            /* allocate both eax and edx */
867
            if (is_reg_allocated(TREG_EAX) || 
1159
            if (is_reg_allocated(TREG_XAX) ||
868
                is_reg_allocated(TREG_EDX))
1160
                is_reg_allocated(TREG_XDX))
869
                goto try_next;
1161
                goto try_next;
870
            op->is_llong = 1;
1162
            op->is_llong = 1;
871
            op->reg = TREG_EAX;
1163
            op->reg = TREG_XAX;
872
            regs_allocated[TREG_EAX] |= reg_mask;
1164
            regs_allocated[TREG_XAX] |= reg_mask;
873
            regs_allocated[TREG_EDX] |= reg_mask;
1165
            regs_allocated[TREG_XDX] |= reg_mask;
874
            break;
1166
            break;
875
        case 'a':
1167
        case 'a':
876
            reg = TREG_EAX;
1168
            reg = TREG_XAX;
877
            goto alloc_reg;
1169
            goto alloc_reg;
878
        case 'b':
1170
        case 'b':
879
            reg = 3;
1171
            reg = 3;
880
            goto alloc_reg;
1172
            goto alloc_reg;
881
        case 'c':
1173
        case 'c':
882
            reg = TREG_ECX;
1174
            reg = TREG_XCX;
883
            goto alloc_reg;
1175
            goto alloc_reg;
884
        case 'd':
1176
        case 'd':
885
            reg = TREG_EDX;
1177
            reg = TREG_XDX;
886
            goto alloc_reg;
1178
            goto alloc_reg;
887
        case 'S':
1179
        case 'S':
888
            reg = 6;
1180
            reg = 6;
889
            goto alloc_reg;
1181
            goto alloc_reg;
890
        case 'D':
1182
        case 'D':
Line 948... Line 1240...
948
                    op->is_memory = 1;
1240
                    op->is_memory = 1;
949
                }
1241
                }
950
            }
1242
            }
951
            break;
1243
            break;
952
        default:
1244
        default:
953
            error("asm constraint %d ('%s') could not be satisfied", 
1245
            tcc_error("asm constraint %d ('%s') could not be satisfied",
954
                  j, op->constraint);
1246
                  j, op->constraint);
955
            break;
1247
            break;
956
        }
1248
        }
957
        /* if a reference is present for that operand, we assign it too */
1249
        /* if a reference is present for that operand, we assign it too */
958
        if (op->input_index >= 0) {
1250
        if (op->input_index >= 0) {
Line 971... Line 1263...
971
            !op->is_memory) {
1263
            !op->is_memory) {
972
            for(reg = 0; reg < 8; reg++) {
1264
            for(reg = 0; reg < 8; reg++) {
973
                if (!(regs_allocated[reg] & REG_OUT_MASK))
1265
                if (!(regs_allocated[reg] & REG_OUT_MASK))
974
                    goto reg_found2;
1266
                    goto reg_found2;
975
            }
1267
            }
976
            error("could not find free output register for reloading");
1268
            tcc_error("could not find free output register for reloading");
977
        reg_found2:
1269
        reg_found2:
978
            *pout_reg = reg;
1270
            *pout_reg = reg;
979
            break;
1271
            break;
980
        }
1272
        }
981
    }
1273
    }
Line 995... Line 1287...
995
    if (*pout_reg >= 0)
1287
    if (*pout_reg >= 0)
996
        printf("out_reg=%d\n", *pout_reg);
1288
        printf("out_reg=%d\n", *pout_reg);
997
#endif
1289
#endif
998
}
1290
}
Line 999... Line 1291...
999
 
1291
 
1000
static void subst_asm_operand(CString *add_str, 
1292
ST_FUNC void subst_asm_operand(CString *add_str,
1001
                              SValue *sv, int modifier)
1293
                              SValue *sv, int modifier)
1002
{
1294
{
1003
    int r, reg, size, val;
1295
    int r, reg, size, val;
Line 1004... Line 1296...
1004
    char buf[64];
1296
    char buf[64];
1005
 
1297
 
1006
    r = sv->r;
1298
    r = sv->r;
1007
    if ((r & VT_VALMASK) == VT_CONST) {
1299
    if ((r & VT_VALMASK) == VT_CONST) {
1008
        if (!(r & VT_LVAL) && modifier != 'c' && modifier != 'n')
1300
        if (!(r & VT_LVAL) && modifier != 'c' && modifier != 'n')
1009
            cstr_ccat(add_str, '$');
1301
            cstr_ccat(add_str, '$');
1010
        if (r & VT_SYM) {
1302
        if (r & VT_SYM) {
1011
            cstr_cat(add_str, get_tok_str(sv->sym->v, NULL));
1303
            cstr_cat(add_str, get_tok_str(sv->sym->v, NULL), -1);
1012
            if (sv->c.i != 0) {
1304
            if ((uint32_t)sv->c.i != 0) {
1013
                cstr_ccat(add_str, '+');
1305
                cstr_ccat(add_str, '+');
1014
            } else {
1306
            } else {
1015
                return;
1307
                return;
1016
            }
1308
            }
1017
        }
1309
        }
1018
        val = sv->c.i;
1310
        val = sv->c.i;
1019
        if (modifier == 'n')
1311
        if (modifier == 'n')
1020
            val = -val;
1312
            val = -val;
1021
        snprintf(buf, sizeof(buf), "%d", sv->c.i);
1313
        snprintf(buf, sizeof(buf), "%d", (int)sv->c.i);
1022
        cstr_cat(add_str, buf);
1314
        cstr_cat(add_str, buf, -1);
1023
    } else if ((r & VT_VALMASK) == VT_LOCAL) {
1315
    } else if ((r & VT_VALMASK) == VT_LOCAL) {
1024
        snprintf(buf, sizeof(buf), "%d(%%ebp)", sv->c.i);
1316
        snprintf(buf, sizeof(buf), "%d(%%ebp)", (int)sv->c.i);
1025
        cstr_cat(add_str, buf);
1317
        cstr_cat(add_str, buf, -1);
1026
    } else if (r & VT_LVAL) {
1318
    } else if (r & VT_LVAL) {
1027
        reg = r & VT_VALMASK;
1319
        reg = r & VT_VALMASK;
1028
        if (reg >= VT_CONST)
1320
        if (reg >= VT_CONST)
1029
            error("internal compiler error");
1321
            tcc_error("internal compiler error");
1030
        snprintf(buf, sizeof(buf), "(%%%s)", 
1322
        snprintf(buf, sizeof(buf), "(%%%s)",
1031
                 get_tok_str(TOK_ASM_eax + reg, NULL));
1323
                 get_tok_str(TOK_ASM_eax + reg, NULL));
1032
        cstr_cat(add_str, buf);
1324
        cstr_cat(add_str, buf, -1);
1033
    } else {
1325
    } else {
1034
        /* register case */
1326
        /* register case */
1035
        reg = r & VT_VALMASK;
1327
        reg = r & VT_VALMASK;
Line 1036... Line 1328...
1036
        if (reg >= VT_CONST)
1328
        if (reg >= VT_CONST)
1037
            error("internal compiler error");
1329
            tcc_error("internal compiler error");
1038
 
1330
 
1039
        /* choose register operand size */
1331
        /* choose register operand size */
1040
        if ((sv->type.t & VT_BTYPE) == VT_BYTE)
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
1041
            size = 1;
1337
        else if ((sv->type.t & VT_BTYPE) == VT_LLONG)
1042
        else if ((sv->type.t & VT_BTYPE) == VT_SHORT)
1338
            size = 8;
1043
            size = 2;
1339
#endif
1044
        else
1340
        else
Line 1045... Line 1341...
1045
            size = 4;
1341
            size = 4;
1046
        if (size == 1 && reg >= 4)
1342
        if (size == 1 && reg >= 4)
1047
            size = 4;
1343
            size = 4;
1048
 
1344
 
1049
        if (modifier == 'b') {
1345
        if (modifier == 'b') {
1050
            if (reg >= 4)
1346
            if (reg >= 4)
1051
                error("cannot use byte register");
1347
                tcc_error("cannot use byte register");
1052
            size = 1;
1348
            size = 1;
1053
        } else if (modifier == 'h') {
1349
        } else if (modifier == 'h') {
1054
            if (reg >= 4)
1350
            if (reg >= 4)
-
 
1351
                tcc_error("cannot use byte register");
-
 
1352
            size = -1;
-
 
1353
        } else if (modifier == 'w') {
-
 
1354
            size = 2;
1055
                error("cannot use byte register");
1355
#ifdef TCC_TARGET_X86_64
Line 1056... Line 1356...
1056
            size = -1;
1356
        } else if (modifier == 'q') {
1057
        } else if (modifier == 'w') {
1357
            size = 8;
1058
            size = 2;
1358
#endif
Line 1069... Line 1369...
1069
            reg = TOK_ASM_ax + reg;
1369
            reg = TOK_ASM_ax + reg;
1070
            break;
1370
            break;
1071
        default:
1371
        default:
1072
            reg = TOK_ASM_eax + reg;
1372
            reg = TOK_ASM_eax + reg;
1073
            break;
1373
            break;
-
 
1374
#ifdef TCC_TARGET_X86_64
-
 
1375
        case 8:
-
 
1376
            reg = TOK_ASM_rax + reg;
-
 
1377
            break;
-
 
1378
#endif
1074
        }
1379
        }
1075
        snprintf(buf, sizeof(buf), "%%%s", get_tok_str(reg, NULL));
1380
        snprintf(buf, sizeof(buf), "%%%s", get_tok_str(reg, NULL));
1076
        cstr_cat(add_str, buf);
1381
        cstr_cat(add_str, buf, -1);
1077
    }
1382
    }
1078
}
1383
}
Line 1079... Line 1384...
1079
 
1384
 
1080
/* generate prolog and epilog code for asm statment */
1385
/* generate prolog and epilog code for asm statement */
1081
static void asm_gen_code(ASMOperand *operands, int nb_operands, 
1386
ST_FUNC void asm_gen_code(ASMOperand *operands, int nb_operands,
1082
                         int nb_outputs, int is_output,
1387
                         int nb_outputs, int is_output,
1083
                         uint8_t *clobber_regs,
1388
                         uint8_t *clobber_regs,
1084
                         int out_reg)
1389
                         int out_reg)
1085
{
1390
{
Line 1097... Line 1402...
1097
    }
1402
    }
1098
    if (!is_output) {
1403
    if (!is_output) {
1099
        /* generate reg save code */
1404
        /* generate reg save code */
1100
        for(i = 0; i < NB_SAVED_REGS; i++) {
1405
        for(i = 0; i < NB_SAVED_REGS; i++) {
1101
            reg = reg_saved[i];
1406
            reg = reg_saved[i];
1102
            if (regs_allocated[reg]) 
1407
            if (regs_allocated[reg]) {
-
 
1408
#ifdef I386_ASM_16
-
 
1409
                if (tcc_state->seg_size == 16)
-
 
1410
                    g(0x66);
-
 
1411
#endif
1103
                g(0x50 + reg);
1412
                g(0x50 + reg);
1104
        }
1413
            }
-
 
1414
        }
Line 1105... Line 1415...
1105
 
1415
 
1106
        /* generate load code */
1416
        /* generate load code */
1107
        for(i = 0; i < nb_operands; i++) {
1417
        for(i = 0; i < nb_operands; i++) {
1108
            op = &operands[i];
1418
            op = &operands[i];
Line 1119... Line 1429...
1119
                    /* load value in register */
1429
                    /* load value in register */
1120
                    load(op->reg, op->vt);
1430
                    load(op->reg, op->vt);
1121
                    if (op->is_llong) {
1431
                    if (op->is_llong) {
1122
                        SValue sv;
1432
                        SValue sv;
1123
                        sv = *op->vt;
1433
                        sv = *op->vt;
1124
                        sv.c.ul += 4;
1434
                        sv.c.i += 4;
1125
                        load(TREG_EDX, &sv);
1435
                        load(TREG_XDX, &sv);
1126
                    }
1436
                    }
1127
                }
1437
                }
1128
            }
1438
            }
1129
        }
1439
        }
1130
    } else {
1440
    } else {
Line 1145... Line 1455...
1145
                } else {
1455
                } else {
1146
                    store(op->reg, op->vt);
1456
                    store(op->reg, op->vt);
1147
                    if (op->is_llong) {
1457
                    if (op->is_llong) {
1148
                        SValue sv;
1458
                        SValue sv;
1149
                        sv = *op->vt;
1459
                        sv = *op->vt;
1150
                        sv.c.ul += 4;
1460
                        sv.c.i += 4;
1151
                        store(TREG_EDX, &sv);
1461
                        store(TREG_XDX, &sv);
1152
                    }
1462
                    }
1153
                }
1463
                }
1154
            }
1464
            }
1155
        }
1465
        }
1156
        /* generate reg restore code */
1466
        /* generate reg restore code */
1157
        for(i = NB_SAVED_REGS - 1; i >= 0; i--) {
1467
        for(i = NB_SAVED_REGS - 1; i >= 0; i--) {
1158
            reg = reg_saved[i];
1468
            reg = reg_saved[i];
1159
            if (regs_allocated[reg]) 
1469
            if (regs_allocated[reg]) {
-
 
1470
#ifdef I386_ASM_16
-
 
1471
                if (tcc_state->seg_size == 16)
-
 
1472
                    g(0x66);
-
 
1473
#endif
1160
                g(0x58 + reg);
1474
                g(0x58 + reg);
1161
        }
1475
            }
1162
    }
1476
        }
1163
}
1477
    }
-
 
1478
}
Line 1164... Line 1479...
1164
 
1479
 
1165
static void asm_clobber(uint8_t *clobber_regs, const char *str)
1480
ST_FUNC void asm_clobber(uint8_t *clobber_regs, const char *str)
1166
{
1481
{
1167
    int reg;
1482
    int reg;
Line 1168... Line 1483...
1168
    TokenSym *ts;
1483
    TokenSym *ts;
Line 1174... Line 1489...
1174
    reg = ts->tok;
1489
    reg = ts->tok;
1175
    if (reg >= TOK_ASM_eax && reg <= TOK_ASM_edi) {
1490
    if (reg >= TOK_ASM_eax && reg <= TOK_ASM_edi) {
1176
        reg -= TOK_ASM_eax;
1491
        reg -= TOK_ASM_eax;
1177
    } else if (reg >= TOK_ASM_ax && reg <= TOK_ASM_di) {
1492
    } else if (reg >= TOK_ASM_ax && reg <= TOK_ASM_di) {
1178
        reg -= TOK_ASM_ax;
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
1179
    } else {
1498
    } else {
1180
        error("invalid clobber register '%s'", str);
1499
        tcc_error("invalid clobber register '%s'", str);
1181
    }
1500
    }
1182
    clobber_regs[reg] = 1;
1501
    clobber_regs[reg] = 1;
1183
}
1502
}