annotate i386/asm.c @ 551:d8b3fa09ca5d

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