| 1 |
// Taken from GDC source tree. Original by David Friedman. |
|---|
| 2 |
// Released under the Artistic License found in dmd/artistic.txt |
|---|
| 3 |
|
|---|
| 4 |
#include "id.h" |
|---|
| 5 |
|
|---|
| 6 |
namespace AsmParserx8664 |
|---|
| 7 |
{ |
|---|
| 8 |
|
|---|
| 9 |
typedef enum |
|---|
| 10 |
{ |
|---|
| 11 |
Reg_Invalid = -1, |
|---|
| 12 |
Reg_EAX = 0, |
|---|
| 13 |
Reg_EBX, |
|---|
| 14 |
Reg_ECX, |
|---|
| 15 |
Reg_EDX, |
|---|
| 16 |
Reg_ESI, |
|---|
| 17 |
Reg_EDI, |
|---|
| 18 |
Reg_EBP, |
|---|
| 19 |
Reg_ESP, |
|---|
| 20 |
Reg_ST, |
|---|
| 21 |
Reg_ST1, Reg_ST2, Reg_ST3, Reg_ST4, Reg_ST5, Reg_ST6, Reg_ST7, |
|---|
| 22 |
Reg_MM0, Reg_MM1, Reg_MM2, Reg_MM3, Reg_MM4, Reg_MM5, Reg_MM6, Reg_MM7, |
|---|
| 23 |
Reg_XMM0, Reg_XMM1, Reg_XMM2, Reg_XMM3, Reg_XMM4, Reg_XMM5, Reg_XMM6, Reg_XMM7, |
|---|
| 24 |
|
|---|
| 25 |
Reg_RAX, Reg_RBX, Reg_RCX, Reg_RDX, Reg_RSI, Reg_RDI, Reg_RBP, Reg_RSP, |
|---|
| 26 |
Reg_R8, Reg_R9, Reg_R10, Reg_R11, Reg_R12, Reg_R13, Reg_R14, Reg_R15, |
|---|
| 27 |
Reg_R8B, Reg_R9B, Reg_R10B, Reg_R11B, Reg_R12B, Reg_R13B, Reg_R14B, Reg_R15B, |
|---|
| 28 |
Reg_R8W, Reg_R9W, Reg_R10W, Reg_R11W, Reg_R12W, Reg_R13W, Reg_R14W, Reg_R15W, |
|---|
| 29 |
Reg_R8D, Reg_R9D, Reg_R10D, Reg_R11D, Reg_R12D, Reg_R13D, Reg_R14D, Reg_R15D, |
|---|
| 30 |
Reg_XMM8, Reg_XMM9, Reg_XMM10, Reg_XMM11, Reg_XMM12, Reg_XMM13, Reg_XMM14, Reg_XMM15, |
|---|
| 31 |
Reg_RIP, |
|---|
| 32 |
Reg_SIL, Reg_DIL, Reg_BPL, Reg_SPL, |
|---|
| 33 |
|
|---|
| 34 |
Reg_EFLAGS, |
|---|
| 35 |
Reg_CS, |
|---|
| 36 |
Reg_DS, |
|---|
| 37 |
Reg_SS, |
|---|
| 38 |
Reg_ES, |
|---|
| 39 |
Reg_FS, |
|---|
| 40 |
Reg_GS, |
|---|
| 41 |
Reg_AX, Reg_BX, Reg_CX, Reg_DX, Reg_SI, Reg_DI, Reg_BP, Reg_SP, |
|---|
| 42 |
Reg_AL, Reg_AH, Reg_BL, Reg_BH, Reg_CL, Reg_CH, Reg_DL, Reg_DH, |
|---|
| 43 |
Reg_CR0, Reg_CR2, Reg_CR3, Reg_CR4, |
|---|
| 44 |
Reg_DR0, Reg_DR1, Reg_DR2, Reg_DR3, Reg_DR6, Reg_DR7, |
|---|
| 45 |
Reg_TR3, Reg_TR4, Reg_TR5, Reg_TR6, Reg_TR7 |
|---|
| 46 |
} Reg; |
|---|
| 47 |
|
|---|
| 48 |
static const int N_Regs = /*gp*/ 8 + /*fp*/ 8 + /*mmx*/ 8 + /*sse*/ 8 + |
|---|
| 49 |
/*seg*/ 6 + /*16bit*/ 8 + /*8bit*/ 8 + /*sys*/ 4+6+5 + /*flags*/ + 1 |
|---|
| 50 |
+ 8 /*RAX, etc*/ |
|---|
| 51 |
+ 8 /*R8-15*/ |
|---|
| 52 |
+ 4 /*SIL, etc. 8-bit*/ |
|---|
| 53 |
+ 8 /*R8-15B*/ |
|---|
| 54 |
+ 8 /*R8-15W*/ |
|---|
| 55 |
+ 8 /*R8-15D*/ |
|---|
| 56 |
+ 8 /*XMM8-15*/ |
|---|
| 57 |
+ 1 /*RIP*/ |
|---|
| 58 |
|
|---|
| 59 |
; |
|---|
| 60 |
|
|---|
| 61 |
#define NULL_TREE "" |
|---|
| 62 |
|
|---|
| 63 |
static struct |
|---|
| 64 |
{ |
|---|
| 65 |
const char * name; |
|---|
| 66 |
std::string gccName; // GAS will take upper case, but GCC won't (needed for the clobber list) |
|---|
| 67 |
Identifier * ident; |
|---|
| 68 |
char size; |
|---|
| 69 |
char baseReg; // %% todo: Reg, Reg_XX |
|---|
| 70 |
} regInfo[N_Regs] = |
|---|
| 71 |
{ |
|---|
| 72 |
{ "EAX", NULL_TREE, NULL, 4, Reg_EAX }, |
|---|
| 73 |
{ "EBX", NULL_TREE, NULL, 4, Reg_EBX }, |
|---|
| 74 |
{ "ECX", NULL_TREE, NULL, 4, Reg_ECX }, |
|---|
| 75 |
{ "EDX", NULL_TREE, NULL, 4, Reg_EDX }, |
|---|
| 76 |
{ "ESI", NULL_TREE, NULL, 4, Reg_ESI }, |
|---|
| 77 |
{ "EDI", NULL_TREE, NULL, 4, Reg_EDI }, |
|---|
| 78 |
{ "EBP", NULL_TREE, NULL, 4, Reg_EBP }, |
|---|
| 79 |
{ "ESP", NULL_TREE, NULL, 4, Reg_ESP }, |
|---|
| 80 |
{ "ST", NULL_TREE, NULL, 10, Reg_ST }, |
|---|
| 81 |
{ "ST(1)", NULL_TREE, NULL,10, Reg_ST1 }, |
|---|
| 82 |
{ "ST(2)", NULL_TREE, NULL,10, Reg_ST2 }, |
|---|
| 83 |
{ "ST(3)", NULL_TREE, NULL,10, Reg_ST3 }, |
|---|
| 84 |
{ "ST(4)", NULL_TREE, NULL,10, Reg_ST4 }, |
|---|
| 85 |
{ "ST(5)", NULL_TREE, NULL,10, Reg_ST5 }, |
|---|
| 86 |
{ "ST(6)", NULL_TREE, NULL,10, Reg_ST6 }, |
|---|
| 87 |
{ "ST(7)", NULL_TREE, NULL,10, Reg_ST7 }, |
|---|
| 88 |
{ "MM0", NULL_TREE, NULL, 8, Reg_MM0 }, |
|---|
| 89 |
{ "MM1", NULL_TREE, NULL, 8, Reg_MM1 }, |
|---|
| 90 |
{ "MM2", NULL_TREE, NULL, 8, Reg_MM2 }, |
|---|
| 91 |
{ "MM3", NULL_TREE, NULL, 8, Reg_MM3 }, |
|---|
| 92 |
{ "MM4", NULL_TREE, NULL, 8, Reg_MM4 }, |
|---|
| 93 |
{ "MM5", NULL_TREE, NULL, 8, Reg_MM5 }, |
|---|
| 94 |
{ "MM6", NULL_TREE, NULL, 8, Reg_MM6 }, |
|---|
| 95 |
{ "MM7", NULL_TREE, NULL, 8, Reg_MM7 }, |
|---|
| 96 |
{ "XMM0", NULL_TREE, NULL, 16, Reg_XMM0 }, |
|---|
| 97 |
{ "XMM1", NULL_TREE, NULL, 16, Reg_XMM1 }, |
|---|
| 98 |
{ "XMM2", NULL_TREE, NULL, 16, Reg_XMM2 }, |
|---|
| 99 |
{ "XMM3", NULL_TREE, NULL, 16, Reg_XMM3 }, |
|---|
| 100 |
{ "XMM4", NULL_TREE, NULL, 16, Reg_XMM4 }, |
|---|
| 101 |
{ "XMM5", NULL_TREE, NULL, 16, Reg_XMM5 }, |
|---|
| 102 |
{ "XMM6", NULL_TREE, NULL, 16, Reg_XMM6 }, |
|---|
| 103 |
{ "XMM7", NULL_TREE, NULL, 16, Reg_XMM7 }, |
|---|
| 104 |
|
|---|
| 105 |
{ "RAX", NULL_TREE, NULL, 8, Reg_RAX }, |
|---|
| 106 |
{ "RBX", NULL_TREE, NULL, 8, Reg_RBX }, |
|---|
| 107 |
{ "RCX", NULL_TREE, NULL, 8, Reg_RCX }, |
|---|
| 108 |
{ "RDX", NULL_TREE, NULL, 8, Reg_RDX }, |
|---|
| 109 |
{ "RSI", NULL_TREE, NULL, 8, Reg_RSI }, |
|---|
| 110 |
{ "RDI", NULL_TREE, NULL, 8, Reg_RDI }, |
|---|
| 111 |
{ "RBP", NULL_TREE, NULL, 8, Reg_RBP }, |
|---|
| 112 |
{ "RSP", NULL_TREE, NULL, 8, Reg_RSP }, |
|---|
| 113 |
{ "R8", NULL_TREE, NULL, 8, Reg_R8 }, |
|---|
| 114 |
{ "R9", NULL_TREE, NULL, 8, Reg_R9 }, |
|---|
| 115 |
{ "R10", NULL_TREE, NULL, 8, Reg_R10 }, |
|---|
| 116 |
{ "R11", NULL_TREE, NULL, 8, Reg_R11 }, |
|---|
| 117 |
{ "R12", NULL_TREE, NULL, 8, Reg_R12 }, |
|---|
| 118 |
{ "R13", NULL_TREE, NULL, 8, Reg_R13 }, |
|---|
| 119 |
{ "R14", NULL_TREE, NULL, 8, Reg_R14 }, |
|---|
| 120 |
{ "R15", NULL_TREE, NULL, 8, Reg_R15 }, |
|---|
| 121 |
{ "R8B", NULL_TREE, NULL, 1, Reg_R8 }, |
|---|
| 122 |
{ "R9B", NULL_TREE, NULL, 1, Reg_R9 }, |
|---|
| 123 |
{ "R10B", NULL_TREE, NULL, 1, Reg_R10 }, |
|---|
| 124 |
{ "R11B", NULL_TREE, NULL, 1, Reg_R11 }, |
|---|
| 125 |
{ "R12B", NULL_TREE, NULL, 1, Reg_R12 }, |
|---|
| 126 |
{ "R13B", NULL_TREE, NULL, 1, Reg_R13 }, |
|---|
| 127 |
{ "R14B", NULL_TREE, NULL, 1, Reg_R14 }, |
|---|
| 128 |
{ "R15B", NULL_TREE, NULL, 1, Reg_R15 }, |
|---|
| 129 |
{ "R8W", NULL_TREE, NULL, 2, Reg_R8 }, |
|---|
| 130 |
{ "R9W", NULL_TREE, NULL, 2, Reg_R9 }, |
|---|
| 131 |
{ "R10W", NULL_TREE, NULL, 2, Reg_R10 }, |
|---|
| 132 |
{ "R11W", NULL_TREE, NULL, 2, Reg_R11 }, |
|---|
| 133 |
{ "R12W", NULL_TREE, NULL, 2, Reg_R12 }, |
|---|
| 134 |
{ "R13W", NULL_TREE, NULL, 2, Reg_R13 }, |
|---|
| 135 |
{ "R14W", NULL_TREE, NULL, 2, Reg_R14 }, |
|---|
| 136 |
{ "R15W", NULL_TREE, NULL, 2, Reg_R15 }, |
|---|
| 137 |
{ "R8D", NULL_TREE, NULL, 4, Reg_R8 }, |
|---|
| 138 |
{ "R9D", NULL_TREE, NULL, 4, Reg_R9 }, |
|---|
| 139 |
{ "R10D", NULL_TREE, NULL, 4, Reg_R10 }, |
|---|
| 140 |
{ "R11D", NULL_TREE, NULL, 4, Reg_R11 }, |
|---|
| 141 |
{ "R12D", NULL_TREE, NULL, 4, Reg_R12 }, |
|---|
| 142 |
{ "R13D", NULL_TREE, NULL, 4, Reg_R13 }, |
|---|
| 143 |
{ "R14D", NULL_TREE, NULL, 4, Reg_R14 }, |
|---|
| 144 |
{ "R15D", NULL_TREE, NULL, 4, Reg_R15 }, |
|---|
| 145 |
{ "XMM8", NULL_TREE, NULL, 16, Reg_XMM8 }, |
|---|
| 146 |
{ "XMM9", NULL_TREE, NULL, 16, Reg_XMM9 }, |
|---|
| 147 |
{ "XMM10", NULL_TREE, NULL, 16, Reg_XMM10 }, |
|---|
| 148 |
{ "XMM11", NULL_TREE, NULL, 16, Reg_XMM11 }, |
|---|
| 149 |
{ "XMM12", NULL_TREE, NULL, 16, Reg_XMM12 }, |
|---|
| 150 |
{ "XMM13", NULL_TREE, NULL, 16, Reg_XMM13 }, |
|---|
| 151 |
{ "XMM14", NULL_TREE, NULL, 16, Reg_XMM14 }, |
|---|
| 152 |
{ "XMM15", NULL_TREE, NULL, 16, Reg_XMM15 }, |
|---|
| 153 |
{ "RIP", NULL_TREE, NULL, 8, Reg_RIP }, |
|---|
| 154 |
{ "SIL", NULL_TREE, NULL, 1, Reg_SIL }, |
|---|
| 155 |
{ "DIL", NULL_TREE, NULL, 1, Reg_DIL }, |
|---|
| 156 |
{ "BPL", NULL_TREE, NULL, 1, Reg_BPL }, |
|---|
| 157 |
{ "SPL", NULL_TREE, NULL, 1, Reg_SPL }, |
|---|
| 158 |
|
|---|
| 159 |
{ "FLAGS", NULL_TREE, NULL, 0, Reg_EFLAGS }, // the gcc name is "flags"; not used in assembler input |
|---|
| 160 |
{ "CS", NULL_TREE, NULL, 2, -1 }, |
|---|
| 161 |
{ "DS", NULL_TREE, NULL, 2, -1 }, |
|---|
| 162 |
{ "SS", NULL_TREE, NULL, 2, -1 }, |
|---|
| 163 |
{ "ES", NULL_TREE, NULL, 2, -1 }, |
|---|
| 164 |
{ "FS", NULL_TREE, NULL, 2, -1 }, |
|---|
| 165 |
{ "GS", NULL_TREE, NULL, 2, -1 }, |
|---|
| 166 |
{ "AX", NULL_TREE, NULL, 2, Reg_EAX }, |
|---|
| 167 |
{ "BX", NULL_TREE, NULL, 2, Reg_EBX }, |
|---|
| 168 |
{ "CX", NULL_TREE, NULL, 2, Reg_ECX }, |
|---|
| 169 |
{ "DX", NULL_TREE, NULL, 2, Reg_EDX }, |
|---|
| 170 |
{ "SI", NULL_TREE, NULL, 2, Reg_ESI }, |
|---|
| 171 |
{ "DI", NULL_TREE, NULL, 2, Reg_EDI }, |
|---|
| 172 |
{ "BP", NULL_TREE, NULL, 2, Reg_EBP }, |
|---|
| 173 |
{ "SP", NULL_TREE, NULL, 2, Reg_ESP }, |
|---|
| 174 |
{ "AL", NULL_TREE, NULL, 1, Reg_EAX }, |
|---|
| 175 |
{ "AH", NULL_TREE, NULL, 1, Reg_EAX }, |
|---|
| 176 |
{ "BL", NULL_TREE, NULL, 1, Reg_EBX }, |
|---|
| 177 |
{ "BH", NULL_TREE, NULL, 1, Reg_EBX }, |
|---|
| 178 |
{ "CL", NULL_TREE, NULL, 1, Reg_ECX }, |
|---|
| 179 |
{ "CH", NULL_TREE, NULL, 1, Reg_ECX }, |
|---|
| 180 |
{ "DL", NULL_TREE, NULL, 1, Reg_EDX }, |
|---|
| 181 |
{ "DH", NULL_TREE, NULL, 1, Reg_EDX }, |
|---|
| 182 |
{ "CR0", NULL_TREE, NULL, 0, -1 }, |
|---|
| 183 |
{ "CR2", NULL_TREE, NULL, 0, -1 }, |
|---|
| 184 |
{ "CR3", NULL_TREE, NULL, 0, -1 }, |
|---|
| 185 |
{ "CR4", NULL_TREE, NULL, 0, -1 }, |
|---|
| 186 |
{ "DR0", NULL_TREE, NULL, 0, -1 }, |
|---|
| 187 |
{ "DR1", NULL_TREE, NULL, 0, -1 }, |
|---|
| 188 |
{ "DR2", NULL_TREE, NULL, 0, -1 }, |
|---|
| 189 |
{ "DR3", NULL_TREE, NULL, 0, -1 }, |
|---|
| 190 |
{ "DR6", NULL_TREE, NULL, 0, -1 }, |
|---|
| 191 |
{ "DR7", NULL_TREE, NULL, 0, -1 }, |
|---|
| 192 |
{ "TR3", NULL_TREE, NULL, 0, -1 }, |
|---|
| 193 |
{ "TR4", NULL_TREE, NULL, 0, -1 }, |
|---|
| 194 |
{ "TR5", NULL_TREE, NULL, 0, -1 }, |
|---|
| 195 |
{ "TR6", NULL_TREE, NULL, 0, -1 }, |
|---|
| 196 |
{ "TR7", NULL_TREE, NULL, 0, -1 } |
|---|
| 197 |
}; |
|---|
| 198 |
|
|---|
| 199 |
typedef enum |
|---|
| 200 |
{ |
|---|
| 201 |
No_Type_Needed, |
|---|
| 202 |
Int_Types, |
|---|
| 203 |
Word_Types, // same as Int_Types, but byte is not allowed |
|---|
| 204 |
FP_Types, |
|---|
| 205 |
FPInt_Types, |
|---|
| 206 |
Byte_NoType, // byte only, but no type suffix |
|---|
| 207 |
} TypeNeeded; |
|---|
| 208 |
|
|---|
| 209 |
typedef enum |
|---|
| 210 |
{ |
|---|
| 211 |
No_Link, |
|---|
| 212 |
Out_Mnemonic, |
|---|
| 213 |
Next_Form |
|---|
| 214 |
} OpLink; |
|---|
| 215 |
|
|---|
| 216 |
typedef enum |
|---|
| 217 |
{ |
|---|
| 218 |
Clb_SizeAX = 0x01, |
|---|
| 219 |
Clb_SizeDXAX = 0x02, |
|---|
| 220 |
Clb_EAX = 0x03, |
|---|
| 221 |
Clb_DXAX_Mask = 0x03, |
|---|
| 222 |
|
|---|
| 223 |
Clb_Flags = 0x04, |
|---|
| 224 |
Clb_DI = 0x08, |
|---|
| 225 |
Clb_SI = 0x10, |
|---|
| 226 |
Clb_CX = 0x20, |
|---|
| 227 |
Clb_ST = 0x40, |
|---|
| 228 |
Clb_SP = 0x80 // Doesn't actually let GCC know the frame pointer is modified |
|---|
| 229 |
} ImplicitClober; |
|---|
| 230 |
|
|---|
| 231 |
// "^ +/..\([A-Za-z_0-9]+\).*" -> " \1," |
|---|
| 232 |
typedef enum |
|---|
| 233 |
{ |
|---|
| 234 |
Op_Invalid, |
|---|
| 235 |
Op_Adjust, |
|---|
| 236 |
Op_Dst, |
|---|
| 237 |
Op_Upd, |
|---|
| 238 |
Op_DstW, |
|---|
| 239 |
Op_DstF, |
|---|
| 240 |
Op_UpdF, |
|---|
| 241 |
Op_DstSrc, |
|---|
| 242 |
Op_DstSrcF, |
|---|
| 243 |
Op_UpdSrcF, |
|---|
| 244 |
Op_DstSrcFW, |
|---|
| 245 |
Op_UpdSrcFW, |
|---|
| 246 |
Op_DstSrcSSE, |
|---|
| 247 |
Op_DstSrcMMX, |
|---|
| 248 |
Op_DstSrcImmS, |
|---|
| 249 |
Op_DstSrcImmM, |
|---|
| 250 |
Op_UpdSrcShft, |
|---|
| 251 |
Op_DstSrcNT, |
|---|
| 252 |
Op_UpdSrcNT, |
|---|
| 253 |
Op_DstMemNT, |
|---|
| 254 |
Op_DstRMBNT, |
|---|
| 255 |
Op_DstRMWNT, |
|---|
| 256 |
Op_UpdUpd, |
|---|
| 257 |
Op_UpdUpdF, |
|---|
| 258 |
Op_Src, |
|---|
| 259 |
Op_SrcRMWNT, |
|---|
| 260 |
Op_SrcW, |
|---|
| 261 |
Op_SrcImm, |
|---|
| 262 |
Op_Src_DXAXF, |
|---|
| 263 |
Op_SrcMemNT, |
|---|
| 264 |
Op_SrcMemNTF, |
|---|
| 265 |
Op_SrcSrc, |
|---|
| 266 |
Op_SrcSrcF, |
|---|
| 267 |
Op_SrcSrcFW, |
|---|
| 268 |
Op_SrcSrcSSEF, |
|---|
| 269 |
Op_SrcSrcMMX, |
|---|
| 270 |
Op_Shift, |
|---|
| 271 |
Op_Branch, |
|---|
| 272 |
Op_CBranch, |
|---|
| 273 |
Op_0, |
|---|
| 274 |
Op_0_AX, |
|---|
| 275 |
Op_0_DXAX, |
|---|
| 276 |
Op_Loop, |
|---|
| 277 |
Op_Flags, |
|---|
| 278 |
Op_F0_ST, |
|---|
| 279 |
Op_F0_P, |
|---|
| 280 |
Op_Fs_P, |
|---|
| 281 |
Op_Fis, |
|---|
| 282 |
Op_Fis_ST, |
|---|
| 283 |
Op_Fis_P, |
|---|
| 284 |
Op_Fid, |
|---|
| 285 |
Op_Fid_P, |
|---|
| 286 |
Op_FidR_P, |
|---|
| 287 |
Op_Ffd, |
|---|
| 288 |
Op_FfdR, |
|---|
| 289 |
Op_Ffd_P, |
|---|
| 290 |
Op_FfdR_P, |
|---|
| 291 |
Op_FfdRR_P, |
|---|
| 292 |
Op_Fd_P, |
|---|
| 293 |
Op_FdST, |
|---|
| 294 |
Op_FMath, |
|---|
| 295 |
Op_FMath0, |
|---|
| 296 |
Op_FMath2, |
|---|
| 297 |
Op_FdSTiSTi, |
|---|
| 298 |
Op_FdST0ST1, |
|---|
| 299 |
Op_FPMath, |
|---|
| 300 |
Op_FCmp, |
|---|
| 301 |
Op_FCmp1, |
|---|
| 302 |
Op_FCmpP, |
|---|
| 303 |
Op_FCmpP1, |
|---|
| 304 |
Op_FCmpFlg, |
|---|
| 305 |
Op_FCmpFlgP, |
|---|
| 306 |
Op_fld, |
|---|
| 307 |
Op_fldR, |
|---|
| 308 |
Op_fxch, |
|---|
| 309 |
Op_fxch1, |
|---|
| 310 |
Op_fxch0, |
|---|
| 311 |
Op_SizedStack, |
|---|
| 312 |
Op_bound, |
|---|
| 313 |
Op_bswap, |
|---|
| 314 |
Op_cmps, |
|---|
| 315 |
Op_cmpsd, |
|---|
| 316 |
Op_cmpsX, |
|---|
| 317 |
Op_cmpxchg8b, |
|---|
| 318 |
Op_cmpxchg, |
|---|
| 319 |
Op_cpuid, |
|---|
| 320 |
Op_enter, |
|---|
| 321 |
Op_fdisi, |
|---|
| 322 |
Op_feni, |
|---|
| 323 |
Op_fsetpm, |
|---|
| 324 |
Op_fXstsw, |
|---|
| 325 |
Op_imul, |
|---|
| 326 |
Op_imul2, |
|---|
| 327 |
Op_imul1, |
|---|
| 328 |
Op_in, |
|---|
| 329 |
Op_ins, |
|---|
| 330 |
Op_insX, |
|---|
| 331 |
Op_iret, |
|---|
| 332 |
Op_iretd, |
|---|
| 333 |
Op_iretq, |
|---|
| 334 |
Op_lods, |
|---|
| 335 |
Op_lodsX, |
|---|
| 336 |
Op_movs, |
|---|
| 337 |
Op_movsd, |
|---|
| 338 |
Op_movsX, |
|---|
| 339 |
Op_movsx, |
|---|
| 340 |
Op_movzx, |
|---|
| 341 |
Op_mul, |
|---|
| 342 |
Op_out, |
|---|
| 343 |
Op_outs, |
|---|
| 344 |
Op_outsX, |
|---|
| 345 |
Op_push, |
|---|
| 346 |
Op_ret, |
|---|
| 347 |
Op_retf, |
|---|
| 348 |
Op_scas, |
|---|
| 349 |
Op_scasX, |
|---|
| 350 |
Op_stos, |
|---|
| 351 |
Op_stosX, |
|---|
| 352 |
Op_xlat, |
|---|
| 353 |
N_AsmOpInfo, |
|---|
| 354 |
Op_Align, |
|---|
| 355 |
Op_Even, |
|---|
| 356 |
Op_Naked, |
|---|
| 357 |
Op_db, |
|---|
| 358 |
Op_ds, |
|---|
| 359 |
Op_di, |
|---|
| 360 |
Op_dl, |
|---|
| 361 |
Op_df, |
|---|
| 362 |
Op_dd, |
|---|
| 363 |
Op_de |
|---|
| 364 |
} AsmOp; |
|---|
| 365 |
|
|---|
| 366 |
typedef enum |
|---|
| 367 |
{ |
|---|
| 368 |
Opr_None = 0, |
|---|
| 369 |
OprC_MRI = 1, |
|---|
| 370 |
OprC_MR = 2, |
|---|
| 371 |
OprC_Mem = 3, |
|---|
| 372 |
OprC_Reg = 4, |
|---|
| 373 |
OprC_Imm = 5, |
|---|
| 374 |
OprC_SSE = 6, |
|---|
| 375 |
OprC_SSE_Mem = 7, |
|---|
| 376 |
OprC_R32 = 8, |
|---|
| 377 |
OprC_RWord = 9, |
|---|
| 378 |
OprC_RFP = 10, |
|---|
| 379 |
OprC_AbsRel = 11, |
|---|
| 380 |
OprC_Relative = 12, |
|---|
| 381 |
OprC_Port = 13, // DX or imm |
|---|
| 382 |
OprC_AX = 14, // AL,AX,EAX |
|---|
| 383 |
OprC_DX = 15, // only DX |
|---|
| 384 |
OprC_MMX = 16, |
|---|
| 385 |
OprC_MMX_Mem = 17, |
|---|
| 386 |
OprC_Shift = 18, // imm or CL |
|---|
| 387 |
|
|---|
| 388 |
Opr_ClassMask = 0x1f, |
|---|
| 389 |
|
|---|
| 390 |
Opr_Dest = 0x20, |
|---|
| 391 |
Opr_Update = 0x60, |
|---|
| 392 |
|
|---|
| 393 |
Opr_NoType = 0x80, |
|---|
| 394 |
} OprVals; |
|---|
| 395 |
|
|---|
| 396 |
|
|---|
| 397 |
typedef struct |
|---|
| 398 |
{ |
|---|
| 399 |
} AsmOprInfo; |
|---|
| 400 |
|
|---|
| 401 |
typedef unsigned char Opr; |
|---|
| 402 |
|
|---|
| 403 |
typedef struct |
|---|
| 404 |
{ |
|---|
| 405 |
Opr operands[3]; |
|---|
| 406 |
unsigned char |
|---|
| 407 |
needsType : 3, |
|---|
| 408 |
implicitClobbers : 8, |
|---|
| 409 |
linkType : 2; |
|---|
| 410 |
unsigned link; |
|---|
| 411 |
|
|---|
| 412 |
/* |
|---|
| 413 |
bool takesLabel() { |
|---|
| 414 |
return operands[0] & Opr_Label; |
|---|
| 415 |
} |
|---|
| 416 |
*/ |
|---|
| 417 |
|
|---|
| 418 |
unsigned nOperands() |
|---|
| 419 |
{ |
|---|
| 420 |
if ( !operands[0] ) |
|---|
| 421 |
return 0; |
|---|
| 422 |
else if ( !operands[1] ) |
|---|
| 423 |
return 1; |
|---|
| 424 |
else if ( !operands[2] ) |
|---|
| 425 |
return 2; |
|---|
| 426 |
else |
|---|
| 427 |
return 3; |
|---|
| 428 |
} |
|---|
| 429 |
} AsmOpInfo; |
|---|
| 430 |
|
|---|
| 431 |
typedef enum |
|---|
| 432 |
{ |
|---|
| 433 |
Mn_fdisi, |
|---|
| 434 |
Mn_feni, |
|---|
| 435 |
Mn_fsetpm, |
|---|
| 436 |
Mn_iretw, |
|---|
| 437 |
Mn_iret, |
|---|
| 438 |
Mn_iretq, |
|---|
| 439 |
Mn_lret, |
|---|
| 440 |
Mn_cmpxchg8b, |
|---|
| 441 |
N_AltMn |
|---|
| 442 |
} Alternate_Mnemonics; |
|---|
| 443 |
|
|---|
| 444 |
static const char * alternateMnemonics[N_AltMn] = |
|---|
| 445 |
{ |
|---|
| 446 |
".byte 0xdb, 0xe1", |
|---|
| 447 |
".byte 0xdb, 0xe0", |
|---|
| 448 |
".byte 0xdb, 0xe4", |
|---|
| 449 |
"iretw", |
|---|
| 450 |
"iret", |
|---|
| 451 |
"iretq", |
|---|
| 452 |
"lret", |
|---|
| 453 |
"cmpxchg8b" |
|---|
| 454 |
}; |
|---|
| 455 |
|
|---|
| 456 |
#define mri OprC_MRI |
|---|
| 457 |
#define mr OprC_MR |
|---|
| 458 |
#define mem OprC_Mem |
|---|
| 459 |
// for now mfp=mem |
|---|
| 460 |
#define mfp OprC_Mem |
|---|
| 461 |
#define reg OprC_Reg |
|---|
| 462 |
#define imm OprC_Imm |
|---|
| 463 |
#define sse OprC_SSE |
|---|
| 464 |
#define ssem OprC_SSE_Mem |
|---|
| 465 |
#define mmx OprC_MMX |
|---|
| 466 |
#define mmxm OprC_MMX_Mem |
|---|
| 467 |
#define r32 OprC_R32 |
|---|
| 468 |
#define rw OprC_RWord |
|---|
| 469 |
#define rfp OprC_RFP |
|---|
| 470 |
#define port OprC_Port |
|---|
| 471 |
#define ax OprC_AX |
|---|
| 472 |
#define dx OprC_DX |
|---|
| 473 |
#define shft OprC_Shift |
|---|
| 474 |
#define D Opr_Dest |
|---|
| 475 |
#define U Opr_Update |
|---|
| 476 |
#define N Opr_NoType |
|---|
| 477 |
//#define L Opr_Label |
|---|
| 478 |
|
|---|
| 479 |
// D=dest, N=notype |
|---|
| 480 |
static AsmOpInfo asmOpInfo[N_AsmOpInfo] = |
|---|
| 481 |
{ |
|---|
| 482 |
/* Op_Invalid */ {}, |
|---|
| 483 |
/* Op_Adjust */ { 0,0,0, 0, Clb_EAX /*just AX*/ }, |
|---|
| 484 |
/* Op_Dst */ { D|mr, 0, 0, 1 }, |
|---|
| 485 |
/* Op_Upd */ { U|mr, 0, 0, 1 }, |
|---|
| 486 |
/* Op_DstW */ { D|mr, 0, 0, Word_Types }, |
|---|
| 487 |
/* Op_DstF */ { D|mr, 0, 0, 1, Clb_Flags }, |
|---|
| 488 |
/* Op_UpdF */ { U|mr, 0, 0, 1, Clb_Flags }, |
|---|
| 489 |
/* Op_DstSrc */ { D|mr, mri, 0,/**/1 }, |
|---|
| 490 |
/* Op_DstSrcF */ { D|mr, mri, 0,/**/1, Clb_Flags }, |
|---|
| 491 |
/* Op_UpdSrcF */ { U|mr, mri, 0,/**/1, Clb_Flags }, |
|---|
| 492 |
/* Op_DstSrcFW */ { D|mr, mri, 0,/**/Word_Types, Clb_Flags }, |
|---|
| 493 |
/* Op_UpdSrcFW */ { U|mr, mri, 0,/**/Word_Types, Clb_Flags }, |
|---|
| 494 |
/* Op_DstSrcSSE */ { U|sse, ssem, 0 }, // some may not be update %% |
|---|
| 495 |
/* Op_DstSrcMMX */ { U|mmx, mmxm, 0 }, // some may not be update %% |
|---|
| 496 |
/* Op_DstSrcImmS*/ { U|sse, ssem, N|imm }, // some may not be update %% |
|---|
| 497 |
/* Op_DstSrcImmM*/ { U|mmx, mmxm, N|imm }, // some may not be update %% |
|---|
| 498 |
/* Op_UpdSrcShft*/ { U|mr, reg, N|shft, 1, Clb_Flags }, // 16/32 only |
|---|
| 499 |
/* Op_DstSrcNT */ { D|mr, mr, 0, 0 }, // used for movd .. operands can be rm32,sse,mmx |
|---|
| 500 |
/* Op_UpdSrcNT */ { U|mr, mr, 0, 0 }, // used for movd .. operands can be rm32,sse,mmx |
|---|
| 501 |
/* Op_DstMemNT */ { D|mem, 0, 0 }, |
|---|
| 502 |
/* Op_DstRMBNT */ { D|mr, 0, 0, Byte_NoType }, |
|---|
| 503 |
/* Op_DstRMWNT */ { D|mr, 0, 0 }, |
|---|
| 504 |
/* Op_UpdUpd */ { U|mr,U|mr, 0,/**/1 }, |
|---|
| 505 |
/* Op_UpdUpdF */ { U|mr,U|mr, 0,/**/1, Clb_Flags }, |
|---|
| 506 |
/* Op_Src */ { mri, 0, 0, 1 }, |
|---|
| 507 |
/* Op_SrcRMWNT */ { mr, 0, 0, 0 }, |
|---|
| 508 |
/* Op_SrcW */ { mri, 0, 0, Word_Types }, |
|---|
| 509 |
/* Op_SrcImm */ { imm }, |
|---|
| 510 |
/* Op_Src_DXAXF */ { mr, 0, 0, 1, Clb_SizeDXAX|Clb_Flags }, |
|---|
| 511 |
/* Op_SrcMemNT */ { mem, 0, 0 }, |
|---|
| 512 |
/* Op_SrcMemNTF */ { mem, 0, 0, 0, Clb_Flags }, |
|---|
| 513 |
/* Op_SrcSrc */ { mr, mri, 0, 1 }, |
|---|
| 514 |
/* Op_SrcSrcF */ { mr, mri, 0, 1, Clb_Flags }, |
|---|
| 515 |
/* Op_SrcSrcFW */ { mr, mri, 0, Word_Types, Clb_Flags }, |
|---|
| 516 |
/* Op_SrcSrcSSEF*/ { sse, ssem, 0, 0, Clb_Flags }, |
|---|
| 517 |
/* Op_SrcSrcMMX */ { mmx, mmx, 0, }, |
|---|
| 518 |
/* Op_Shift */ { D|mr,N|shft, 0,/**/1, Clb_Flags }, |
|---|
| 519 |
/* Op_Branch */ { mri }, |
|---|
| 520 |
/* Op_CBranch */ { imm }, |
|---|
| 521 |
/* Op_0 */ { 0,0,0 }, |
|---|
| 522 |
/* Op_0_AX */ { 0,0,0, 0, Clb_SizeAX }, |
|---|
| 523 |
/* Op_0_DXAX */ { 0,0,0, 0, Clb_SizeDXAX }, // but for cwd/cdq -- how do know the size.. |
|---|
| 524 |
/* Op_Loop */ { imm, 0, 0, 0, Clb_CX }, |
|---|
| 525 |
/* Op_Flags */ { 0,0,0, 0, Clb_Flags }, |
|---|
| 526 |
/* Op_F0_ST */ { 0,0,0, 0, Clb_ST }, |
|---|
| 527 |
/* Op_F0_P */ { 0,0,0, 0, Clb_ST }, // push, pops, etc. not sure how to inform gcc.. |
|---|
| 528 |
/* Op_Fs_P */ { mem, 0, 0, 0, Clb_ST }, // " |
|---|
| 529 |
/* Op_Fis */ { mem, 0, 0, FPInt_Types }, // only 16bit and 32bit, DMD defaults to 16bit |
|---|
| 530 |
/* Op_Fis_ST */ { mem, 0, 0, FPInt_Types, Clb_ST }, // " |
|---|
| 531 |
/* Op_Fis_P */ { mem, 0, 0, FPInt_Types, Clb_ST }, // push and pop, fild so also 64 bit |
|---|
| 532 |
/* Op_Fid */ { D|mem, 0, 0, FPInt_Types }, // only 16bit and 32bit, DMD defaults to 16bit |
|---|
| 533 |
/* Op_Fid_P */ { D|mem, 0, 0, FPInt_Types, Clb_ST, Next_Form, Op_FidR_P }, // push and pop, fild so also 64 bit |
|---|
| 534 |
/* Op_FidR_P */ { D|mem,rfp, 0, FPInt_Types, Clb_ST }, // push and pop, fild so also 64 bit |
|---|
| 535 |
/* Op_Ffd */ { D|mfp, 0, 0, FP_Types, 0, Next_Form, Op_FfdR }, // only 16bit and 32bit, DMD defaults to 16bit, reg form doesn't need type |
|---|
| 536 |
/* Op_FfdR */ { D|rfp, 0, 0 }, |
|---|
| 537 |
/* Op_Ffd_P */ { D|mfp, 0, 0, FP_Types, Clb_ST, Next_Form, Op_FfdR_P }, // pop, fld so also 80 bit, " |
|---|
| 538 |
/* Op_FfdR_P */ { D|rfp, 0, 0, 0, Clb_ST, Next_Form, Op_FfdRR_P }, |
|---|
| 539 |
/* Op_FfdRR_P */ { D|rfp,rfp, 0, 0, Clb_ST }, |
|---|
| 540 |
/* Op_Fd_P */ { D|mem, 0, 0, 0, Clb_ST }, // " |
|---|
| 541 |
/* Op_FdST */ { D|rfp, 0, 0 }, |
|---|
| 542 |
/* Op_FMath */ { mfp, 0, 0, FP_Types, Clb_ST, Next_Form, Op_FMath0 }, // and only single or double prec |
|---|
| 543 |
/* Op_FMath0 */ { 0, 0, 0, 0, Clb_ST, Next_Form, Op_FMath2 }, // pops |
|---|
| 544 |
/* Op_FMath2 */ { D|rfp, rfp, 0, 0, Clb_ST, Next_Form, Op_FdST0ST1 }, // and only single or double prec |
|---|
| 545 |
/* Op_FdSTiSTi */ { D|rfp, rfp, 0, }, |
|---|
| 546 |
/* Op_FdST0ST1 */ { 0, 0, 0, }, |
|---|
| 547 |
/* Op_FPMath */ { D|rfp, rfp, 0, 0, Clb_ST, Next_Form, Op_F0_P }, // pops |
|---|
| 548 |
/* Op_FCmp */ { mfp, 0, 0, FP_Types, 0, Next_Form, Op_FCmp1 }, // DMD defaults to float ptr |
|---|
| 549 |
/* Op_FCmp1 */ { rfp, 0, 0, 0, 0, Next_Form, Op_0 }, |
|---|
| 550 |
/* Op_FCmpP */ { mfp, 0, 0, FP_Types, 0, Next_Form, Op_FCmpP1 }, // pops |
|---|
| 551 |
/* Op_FCmpP1 */ { rfp, 0, 0, 0, 0, Next_Form, Op_F0_P }, // pops |
|---|
| 552 |
/* Op_FCmpFlg */ { rfp, rfp, 0, 0, Clb_Flags }, |
|---|
| 553 |
/* Op_FCmpFlgP */ { rfp, rfp, 0, 0, Clb_Flags }, // pops |
|---|
| 554 |
/* Op_fld */ { mfp, 0, 0, FP_Types, Clb_ST, Next_Form, Op_fldR }, |
|---|
| 555 |
/* Op_fldR */ { rfp, 0, 0, 0, Clb_ST }, |
|---|
| 556 |
/* Op_fxch */ { D|rfp,D|rfp, 0, 0, Clb_ST, Next_Form, Op_fxch1 }, // not in intel manual?, but DMD allows it (gas won't), second arg must be ST |
|---|
| 557 |
/* Op_fxch1 */ { D|rfp, 0, 0, 0, Clb_ST, Next_Form, Op_fxch0 }, |
|---|
| 558 |
/* Op_fxch0 */ { 0, 0, 0, 0, Clb_ST }, // Also clobbers ST(1) |
|---|
| 559 |
/* Op_SizedStack*/ { 0, 0, 0, 0, Clb_SP }, // type suffix special case |
|---|
| 560 |
/* Op_bound */ { mr, mri, 0, Word_Types }, // operands *not* reversed for gas |
|---|
| 561 |
/* Op_bswap */ { D|r32 }, |
|---|
| 562 |
/* Op_cmps */ { mem, mem, 0, 1, Clb_DI|Clb_SI|Clb_Flags }, |
|---|
| 563 |
/* Op_cmpsd */ { 0, 0, 0, 0, Clb_DI|Clb_SI|Clb_Flags, Next_Form, Op_DstSrcImmS }, |
|---|
| 564 |
/* Op_cmpsX */ { 0, 0, 0, 0, Clb_DI|Clb_SI|Clb_Flags }, |
|---|
| 565 |
/* Op_cmpxchg8b */ { D|mem/*64*/,0,0, 0, Clb_SizeDXAX/*32*/|Clb_Flags, Out_Mnemonic, Mn_cmpxchg8b }, |
|---|
| 566 |
/* Op_cmpxchg */ { D|mr, reg, 0, 1, Clb_SizeAX|Clb_Flags }, |
|---|
| 567 |
/* Op_cpuid */ { 0,0,0 }, // Clobbers eax, ebx, ecx, and edx. Handled specially below. |
|---|
| 568 |
/* Op_enter */ { imm, imm }, // operands *not* reversed for gas, %% inform gcc of EBP clobber?, |
|---|
| 569 |
/* Op_fdisi */ { 0,0,0, 0, 0, Out_Mnemonic, Mn_fdisi }, |
|---|
| 570 |
/* Op_feni */ { 0,0,0, 0, 0, Out_Mnemonic, Mn_feni }, |
|---|
| 571 |
/* Op_fsetpm */ { 0,0,0, 0, 0, Out_Mnemonic, Mn_fsetpm }, |
|---|
| 572 |
/* Op_fXstsw */ { D|mr, 0, 0, }, // ax is the only allowed register |
|---|
| 573 |
/* Op_imul */ { D|reg, mr, imm, 1, Clb_Flags, Next_Form, Op_imul2 }, // 16/32 only |
|---|
| 574 |
/* Op_imul2 */ { D|reg, mri, 0, 1, Clb_Flags, Next_Form, Op_imul1 }, // 16/32 only |
|---|
| 575 |
/* Op_imul1 */ { mr, 0, 0, 1, Clb_Flags|Clb_SizeDXAX }, |
|---|
| 576 |
/* Op_in */ { D|ax,N|port,0, 1 }, |
|---|
| 577 |
/* Op_ins */ { mem,N|dx, 0, 1, Clb_DI }, // can't override ES segment for this one |
|---|
| 578 |
/* Op_insX */ { 0, 0, 0, 0, Clb_DI }, // output segment overrides %% needs work |
|---|
| 579 |
/* Op_iret */ { 0,0,0, 0, 0, Out_Mnemonic, Mn_iretw }, |
|---|
| 580 |
/* Op_iretd */ { 0,0,0, 0, 0, Out_Mnemonic, Mn_iret }, |
|---|
| 581 |
/* Op_iretq */ { 0,0,0, 0, 0, Out_Mnemonic, Mn_iretq }, |
|---|
| 582 |
/* Op_lods */ { mem, 0, 0, 1, Clb_SI }, |
|---|
| 583 |
/* Op_lodsX */ { 0, 0, 0, 0, Clb_SI }, |
|---|
| 584 |
/* Op_movs */ { mem, mem, 0, 1, Clb_DI|Clb_SI }, // only src/DS can be overridden |
|---|
| 585 |
/* Op_movsd */ { 0, 0, 0, 0, Clb_DI|Clb_SI, Next_Form, Op_DstSrcSSE }, // %% gas doesn't accept movsd .. has to movsl |
|---|
| 586 |
/* Op_movsX */ { 0, 0, 0, 0, Clb_DI|Clb_SI }, |
|---|
| 587 |
/* Op_movsx */ { D|reg, mr, 0, 1 }, // type suffix is special case |
|---|
| 588 |
/* Op_movzx */ { D|reg, mr, 0, 1 }, // type suffix is special case |
|---|
| 589 |
/* Op_mul */ { U|ax, mr, 0, 1, Clb_SizeDXAX|Clb_Flags, Next_Form, Op_Src_DXAXF }, |
|---|
| 590 |
/* Op_out */ { N|port,ax, 0, 1 }, |
|---|
| 591 |
/* Op_outs */ { N|dx, mem, 0, 1, Clb_SI }, |
|---|
| 592 |
/* Op_outsX */ { 0, 0, 0, 0, Clb_SI }, |
|---|
| 593 |
/* Op_push */ { mri, 0, 0, 0, Clb_SP }, // would be Op_SrcW, but DMD defaults to 32-bit for immediate form |
|---|
| 594 |
/* Op_ret */ { imm, 0, 0, 0, 0, Next_Form, Op_0 }, |
|---|
| 595 |
/* Op_retf */ { 0, 0, 0, 0, 0, Out_Mnemonic, Mn_lret }, |
|---|
| 596 |
/* Op_scas */ { mem, 0, 0, 1, Clb_DI|Clb_Flags }, |
|---|
| 597 |
/* Op_scasX */ { 0, 0, 0, 0, Clb_DI|Clb_Flags }, |
|---|
| 598 |
/* Op_stos */ { mem, 0, 0, 1, Clb_DI }, |
|---|
| 599 |
/* Op_stosX */ { 0, 0, 0, 0, Clb_DI }, |
|---|
| 600 |
/* Op_xlat */ { mem, 0, 0, 0, Clb_SizeAX } |
|---|
| 601 |
|
|---|
| 602 |
/// * Op_arpl */ { D|mr, reg }, // 16 only -> DstSrc |
|---|
| 603 |
/// * Op_bsX */ { rw, mrw, 0, 1, Clb_Flags },//->srcsrcf |
|---|
| 604 |
/// * Op_bt */ { mrw, riw, 0, 1, Clb_Flags },//->srcsrcf |
|---|
| 605 |
/// * Op_btX */ { D|mrw, riw, 0, 1, Clb_Flags },//->dstsrcf .. immediate does not contribute to size |
|---|
| 606 |
/// * Op_cmovCC */ { D|rw, mrw, 0, 1 } // ->dstsrc |
|---|
| 607 |
}; |
|---|
| 608 |
|
|---|
| 609 |
#undef mri |
|---|
| 610 |
#undef mr |
|---|
| 611 |
#undef mem |
|---|
| 612 |
#undef mfp |
|---|
| 613 |
#undef reg |
|---|
| 614 |
#undef imm |
|---|
| 615 |
#undef sse |
|---|
| 616 |
#undef ssem |
|---|
| 617 |
#undef mmx |
|---|
| 618 |
#undef mmxm |
|---|
| 619 |
#undef r32 |
|---|
| 620 |
#undef rw |
|---|
| 621 |
#undef rfp |
|---|
| 622 |
#undef port |
|---|
| 623 |
#undef ax |
|---|
| 624 |
#undef dx |
|---|
| 625 |
#undef shft |
|---|
| 626 |
#undef D |
|---|
| 627 |
#undef U |
|---|
| 628 |
#undef N |
|---|
| 629 |
//#undef L |
|---|
| 630 |
|
|---|
| 631 |
typedef struct |
|---|
| 632 |
{ |
|---|
| 633 |
const char * inMnemonic; |
|---|
| 634 |
AsmOp asmOp; |
|---|
| 635 |
} AsmOpEnt; |
|---|
| 636 |
|
|---|
| 637 |
/* Some opcodes which have data size restrictions, but we don't check |
|---|
| 638 |
|
|---|
| 639 |
cmov, l<segreg> ?, lea, lsl, shld |
|---|
| 640 |
|
|---|
| 641 |
todo: push <immediate> is always the 32-bit form, even tho push <mem> is 16-bit |
|---|
| 642 |
*/ |
|---|
| 643 |
|
|---|
| 644 |
static AsmOpEnt opData[] = |
|---|
| 645 |
{ |
|---|
| 646 |
{ "adc", Op_UpdSrcF }, |
|---|
| 647 |
{ "add", Op_UpdSrcF }, |
|---|
| 648 |
{ "addpd", Op_DstSrcSSE }, |
|---|
| 649 |
{ "addps", Op_DstSrcSSE }, |
|---|
| 650 |
{ "addq", Op_DstSrcSSE }, |
|---|
| 651 |
{ "addsd", Op_DstSrcSSE }, |
|---|
| 652 |
{ "addss", Op_DstSrcSSE }, |
|---|
| 653 |
{ "addsubpd", Op_DstSrcSSE }, |
|---|
| 654 |
{ "addsubps", Op_DstSrcSSE }, |
|---|
| 655 |
{ "and", Op_UpdSrcF }, |
|---|
| 656 |
{ "andnpd", Op_DstSrcSSE }, |
|---|
| 657 |
{ "andnps", Op_DstSrcSSE }, |
|---|
| 658 |
{ "andpd", Op_DstSrcSSE }, |
|---|
| 659 |
{ "andps", Op_DstSrcSSE }, |
|---|
| 660 |
{ "bsf", Op_SrcSrcFW }, |
|---|
| 661 |
{ "bsr", Op_SrcSrcFW }, |
|---|
| 662 |
{ "bswap", Op_bswap }, |
|---|
| 663 |
{ "bt", Op_SrcSrcFW }, |
|---|
| 664 |
{ "btc", Op_UpdSrcFW }, |
|---|
| 665 |
{ "btr", Op_UpdSrcFW }, |
|---|
| 666 |
{ "bts", Op_UpdSrcFW }, |
|---|
| 667 |
{ "call", Op_Branch }, |
|---|
| 668 |
{ "callf", Op_Branch }, |
|---|
| 669 |
{ "cbw", Op_0_AX }, |
|---|
| 670 |
{ "cdqe", Op_0_DXAX }, |
|---|
| 671 |
{ "clc", Op_Flags }, |
|---|
| 672 |
{ "cld", Op_Flags }, |
|---|
| 673 |
{ "clflush",Op_SrcMemNT }, |
|---|
| 674 |
{ "cli", Op_Flags }, |
|---|
| 675 |
{ "clts", Op_0 }, |
|---|
| 676 |
{ "cmc", Op_Flags }, |
|---|
| 677 |
{ "cmova", Op_DstSrc }, |
|---|
| 678 |
{ "cmovae", Op_DstSrc }, |
|---|
| 679 |
{ "cmovb", Op_DstSrc }, |
|---|
| 680 |
{ "cmovbe", Op_DstSrc }, |
|---|
| 681 |
{ "cmovc", Op_DstSrc }, |
|---|
| 682 |
{ "cmove", Op_DstSrc }, |
|---|
| 683 |
{ "cmovg", Op_DstSrc }, |
|---|
| 684 |
{ "cmovge", Op_DstSrc }, |
|---|
| 685 |
{ "cmovl", Op_DstSrc }, |
|---|
| 686 |
{ "cmovle", Op_DstSrc }, |
|---|
| 687 |
{ "cmovna", Op_DstSrc }, |
|---|
| 688 |
{ "cmovnae",Op_DstSrc }, |
|---|
| 689 |
{ "cmovnb", Op_DstSrc }, |
|---|
| 690 |
{ "cmovnbe",Op_DstSrc }, |
|---|
| 691 |
{ "cmovnc", Op_DstSrc }, |
|---|
| 692 |
{ "cmovne", Op_DstSrc }, |
|---|
| 693 |
{ "cmovng", Op_DstSrc }, |
|---|
| 694 |
{ "cmovnge",Op_DstSrc }, |
|---|
| 695 |
{ "cmovnl", Op_DstSrc }, |
|---|
| 696 |
{ "cmovnle",Op_DstSrc }, |
|---|
| 697 |
{ "cmovno", Op_DstSrc }, |
|---|
| 698 |
{ "cmovnp", Op_DstSrc }, |
|---|
| 699 |
{ "cmovns", Op_DstSrc }, |
|---|
| 700 |
{ "cmovnz", Op_DstSrc }, |
|---|
| 701 |
{ "cmovo", Op_DstSrc }, |
|---|
| 702 |
{ "cmovp", Op_DstSrc }, |
|---|
| 703 |
{ "cmovpe", Op_DstSrc }, |
|---|
| 704 |
{ "cmovpo", Op_DstSrc }, |
|---|
| 705 |
{ "cmovs", Op_DstSrc }, |
|---|
| 706 |
{ "cmovz", Op_DstSrc }, |
|---|
| 707 |
{ "cmp", Op_SrcSrcF }, |
|---|
| 708 |
{ "cmppd", Op_DstSrcImmS }, |
|---|
| 709 |
{ "cmpps", Op_DstSrcImmS }, |
|---|
| 710 |
{ "cmpq", Op_DstSrcNT }, |
|---|
| 711 |
{ "cmps", Op_cmps }, |
|---|
| 712 |
{ "cmpsb", Op_cmpsX }, |
|---|
| 713 |
{ "cmpsd", Op_cmpsd }, // string cmp, and SSE cmp |
|---|
| 714 |
{ "cmpss", Op_DstSrcImmS }, |
|---|
| 715 |
{ "cmpsw", Op_cmpsX }, |
|---|
| 716 |
{ "cmpsq", Op_cmpsX }, |
|---|
| 717 |
/* |
|---|
| 718 |
{ "cdqe", Op_0_DXAX }, |
|---|
| 719 |
{ "cmpsq", Op_cmpsX }, |
|---|
| 720 |
{ "cmpxch16b", Op_cmpxchg16b }, |
|---|
| 721 |
{ "cqo", Op_0_DXAX }, |
|---|
| 722 |
{ "lodsq", Op_lodsX }, |
|---|
| 723 |
{ "movsq", Op_movsX }, |
|---|
| 724 |
{ "popfq", Op_SizedStack }, |
|---|
| 725 |
{ "pushfq", Op_SizedStack }, |
|---|
| 726 |
{ "scasq", Op_scasX }, |
|---|
| 727 |
{ "stosq", Op_stosX }, |
|---|
| 728 |
{ "iretq", Op_iretd }, |
|---|
| 729 |
{ "swapgs", Op_0 }, |
|---|
| 730 |
{ "extrq", Op_Extrq }, |
|---|
| 731 |
{ "movsxq", Op_movsxq }, |
|---|
| 732 |
|
|---|
| 733 |
{ "clgi", Op_Flags }, |
|---|
| 734 |
{ "invlpga", Op_SrcMemNT }, |
|---|
| 735 |
{ "rdtscp", Op_0_DXAX }, |
|---|
| 736 |
{ "stgi", Op_Flags }, |
|---|
| 737 |
*/ |
|---|
| 738 |
|
|---|
| 739 |
{ "cmpxch16b", Op_cmpxchg8b }, |
|---|
| 740 |
{ "cmpxch8b", Op_cmpxchg8b }, // %% DMD opcode typo? |
|---|
| 741 |
{ "cmpxchg", Op_cmpxchg }, |
|---|
| 742 |
{ "comisd", Op_SrcSrcSSEF }, |
|---|
| 743 |
{ "comiss", Op_SrcSrcSSEF }, |
|---|
| 744 |
{ "cpuid", Op_cpuid }, |
|---|
| 745 |
{ "cvtdq2pd", Op_DstSrcSSE }, |
|---|
| 746 |
{ "cvtdq2ps", Op_DstSrcSSE }, |
|---|
| 747 |
{ "cvtpd2dq", Op_DstSrcSSE }, |
|---|
| 748 |
{ "cvtpd2pi", Op_DstSrcSSE }, |
|---|
| 749 |
{ "cvtpd2ps", Op_DstSrcSSE }, |
|---|
| 750 |
{ "cvtpi2pd", Op_DstSrcSSE }, |
|---|
| 751 |
{ "cvtpi2ps", Op_DstSrcSSE }, |
|---|
| 752 |
{ "cvtps2dq", Op_DstSrcSSE }, |
|---|
| 753 |
{ "cvtps2pd", Op_DstSrcSSE }, |
|---|
| 754 |
{ "cvtps2pi", Op_DstSrcSSE }, |
|---|
| 755 |
{ "cvtsd2si", Op_DstSrcSSE }, |
|---|
| 756 |
{ "cvtsd2ss", Op_DstSrcSSE }, |
|---|
| 757 |
{ "cvtsi2sd", Op_DstSrcSSE }, |
|---|
| 758 |
{ "cvtsi2ss", Op_DstSrcSSE }, |
|---|
| 759 |
{ "cvtss2sd", Op_DstSrcSSE }, |
|---|
| 760 |
{ "cvtss2si", Op_DstSrcSSE }, |
|---|
| 761 |
{ "cvttpd2dq", Op_DstSrcSSE }, |
|---|
| 762 |
{ "cvttpd2pi", Op_DstSrcSSE }, |
|---|
| 763 |
{ "cvttps2dq", Op_DstSrcSSE }, |
|---|
| 764 |
{ "cvttps2pi", Op_DstSrcSSE }, |
|---|
| 765 |
{ "cvttsd2si", Op_DstSrcSSE }, |
|---|
| 766 |
{ "cvttss2si", Op_DstSrcSSE }, |
|---|
| 767 |
{ "cwd", Op_0_DXAX }, |
|---|
| 768 |
{ "cwde", Op_0_DXAX }, |
|---|
| 769 |
//{ "da", Op_ },// dunno what this is -- takes labels? |
|---|
| 770 |
{ "db", Op_db }, |
|---|
| 771 |
{ "dd", Op_dd }, |
|---|
| 772 |
{ "de", Op_de }, |
|---|
| 773 |
{ "dec", Op_UpdF }, |
|---|
| 774 |
{ "df", Op_df }, |
|---|
| 775 |
{ "di", Op_di }, |
|---|
| 776 |
{ "div", Op_Src_DXAXF }, |
|---|
| 777 |
{ "divpd", Op_DstSrcSSE }, |
|---|
| 778 |
{ "divps", Op_DstSrcSSE }, |
|---|
| 779 |
{ "divsd", Op_DstSrcSSE }, |
|---|
| 780 |
{ "divss", Op_DstSrcSSE }, |
|---|
| 781 |
{ "dl", Op_dl }, |
|---|
| 782 |
{ "dq", Op_dl }, |
|---|
| 783 |
{ "ds", Op_ds }, |
|---|
| 784 |
{ "dt", Op_de }, |
|---|
| 785 |
{ "dw", Op_ds }, |
|---|
| 786 |
{ "emms", Op_0 }, // clobber all mmx/fp? |
|---|
| 787 |
{ "enter", Op_enter }, |
|---|
| 788 |
{ "f2xm1", Op_F0_ST }, // %% most of these are update... |
|---|
| 789 |
{ "fabs", Op_F0_ST }, |
|---|
| 790 |
{ "fadd", Op_FMath }, |
|---|
| 791 |
{ "faddp", Op_FPMath }, |
|---|
| 792 |
{ "fbld", Op_Fs_P }, |
|---|
| 793 |
{ "fbstp", Op_Fd_P }, |
|---|
| 794 |
{ "fchs", Op_F0_ST }, |
|---|
| 795 |
{ "fclex", Op_0 }, |
|---|
| 796 |
{ "fcmovb", Op_FdSTiSTi }, // but only ST(0) can be the destination -- should be FdST0STi |
|---|
| 797 |
{ "fcmovbe", Op_FdSTiSTi }, |
|---|
| 798 |
{ "fcmove", Op_FdSTiSTi }, |
|---|
| 799 |
{ "fcmovnb", Op_FdSTiSTi }, |
|---|
| 800 |
{ "fcmovnbe", Op_FdSTiSTi }, |
|---|
| 801 |
{ "fcmovne", Op_FdSTiSTi }, |
|---|
| 802 |
{ "fcmovnu", Op_FdSTiSTi }, |
|---|
| 803 |
{ "fcmovu", Op_FdSTiSTi }, |
|---|
| 804 |
{ "fcom", Op_FCmp }, |
|---|
| 805 |
{ "fcomi", Op_FCmpFlg }, |
|---|
| 806 |
{ "fcomip", Op_FCmpFlgP }, |
|---|
| 807 |
{ "fcomp", Op_FCmpP }, |
|---|
| 808 |
{ "fcompp", Op_F0_P }, // pops twice |
|---|
| 809 |
{ "fcos", Op_F0_ST }, |
|---|
| 810 |
{ "fdecstp",Op_F0_P }, // changes stack |
|---|
| 811 |
{ "fdisi", Op_fdisi }, |
|---|
| 812 |
{ "fdiv", Op_FMath }, |
|---|
| 813 |
{ "fdivp", Op_FPMath }, |
|---|
| 814 |
{ "fdivr", Op_FMath }, |
|---|
| 815 |
{ "fdivrp", Op_FPMath }, |
|---|
| 816 |
{ "feni", Op_feni }, |
|---|
| 817 |
{ "ffree", Op_FdST }, |
|---|
| 818 |
{ "fiadd", Op_Fis_ST }, |
|---|
| 819 |
{ "ficom", Op_Fis }, |
|---|
| 820 |
{ "ficomp", Op_Fis_P }, |
|---|
| 821 |
{ "fidiv", Op_Fis_ST }, |
|---|
| 822 |
{ "fidivr", Op_Fis_ST }, |
|---|
| 823 |
{ "fild", Op_Fis_P }, |
|---|
| 824 |
{ "fimul", Op_Fis_ST }, |
|---|
| 825 |
{ "fincstp",Op_F0_P }, |
|---|
| 826 |
{ "finit", Op_F0_P }, |
|---|
| 827 |
{ "fist", Op_Fid }, // only 16,32bit |
|---|
| 828 |
{ "fistp", Op_Fid_P }, |
|---|
| 829 |
{ "fisttp", Op_Fid_P }, |
|---|
| 830 |
{ "fisub", Op_Fis_ST }, |
|---|
| 831 |
{ "fisubr", Op_Fis_ST }, |
|---|
| 832 |
{ "fld", Op_fld }, |
|---|
| 833 |
{ "fld1", Op_F0_P }, |
|---|
| 834 |
{ "fldcw", Op_SrcMemNT }, |
|---|
| 835 |
{ "fldenv", Op_SrcMemNT }, |
|---|
| 836 |
{ "fldl2e", Op_F0_P }, |
|---|
| 837 |
{ "fldl2t", Op_F0_P }, |
|---|
| 838 |
{ "fldlg2", Op_F0_P }, |
|---|
| 839 |
{ "fldln2", Op_F0_P }, |
|---|
| 840 |
{ "fldpi", Op_F0_P }, |
|---|
| 841 |
{ "fldz", Op_F0_P }, |
|---|
| 842 |
{ "fmul", Op_FMath }, |
|---|
| 843 |
{ "fmulp", Op_FPMath }, |
|---|
| 844 |
{ "fnclex", Op_0 }, |
|---|
| 845 |
{ "fndisi", Op_fdisi }, // ?? |
|---|
| 846 |
{ "fneni", Op_feni }, // ?? |
|---|
| 847 |
{ "fninit", Op_0 }, |
|---|
| 848 |
{ "fnop", Op_0 }, |
|---|
| 849 |
{ "fnsave", Op_DstMemNT }, |
|---|
| 850 |
{ "fnstcw", Op_DstMemNT }, |
|---|
| 851 |
{ "fnstenv",Op_DstMemNT }, |
|---|
| 852 |
{ "fnstsw", Op_fXstsw }, |
|---|
| 853 |
{ "fpatan", Op_F0_P }, // pop and modify new ST |
|---|
| 854 |
{ "fprem", Op_F0_ST }, |
|---|
| 855 |
{ "fprem1", Op_F0_ST }, |
|---|
| 856 |
{ "fptan", Op_F0_P }, // modify ST and push 1.0 |
|---|
| 857 |
{ "frndint",Op_F0_ST }, |
|---|
| 858 |
{ "frstor", Op_SrcMemNT }, // but clobbers everything |
|---|
| 859 |
{ "fsave", Op_DstMemNT }, |
|---|
| 860 |
{ "fscale", Op_F0_ST }, |
|---|
| 861 |
{ "fsetpm", Op_fsetpm }, |
|---|
| 862 |
{ "fsin", Op_F0_ST }, |
|---|
| 863 |
{ "fsincos",Op_F0_P }, |
|---|
| 864 |
{ "fsqrt", Op_F0_ST }, |
|---|
| 865 |
{ "fst", Op_Ffd }, |
|---|
| 866 |
{ "fstcw", Op_DstMemNT }, |
|---|
| 867 |
{ "fstenv", Op_DstMemNT }, |
|---|
| 868 |
{ "fstp", Op_Ffd_P }, |
|---|
| 869 |
{ "fstsw", Op_fXstsw }, |
|---|
| 870 |
{ "fsub", Op_FMath }, |
|---|
| 871 |
{ "fsubp", Op_FPMath }, |
|---|
| 872 |
{ "fsubr", Op_FMath }, |
|---|
| 873 |
{ "fsubrp", Op_FPMath }, |
|---|
| 874 |
{ "ftst", Op_0 }, |
|---|
| 875 |
{ "fucom", Op_FCmp }, |
|---|
| 876 |
{ "fucomi", Op_FCmpFlg }, |
|---|
| 877 |
{ "fucomip",Op_FCmpFlgP }, |
|---|
| 878 |
{ "fucomp", Op_FCmpP }, |
|---|
| 879 |
{ "fucompp",Op_F0_P }, // pops twice |
|---|
| 880 |
{ "fwait", Op_0 }, |
|---|
| 881 |
{ "fxam", Op_0 }, |
|---|
| 882 |
{ "fxch", Op_fxch }, |
|---|
| 883 |
{ "fxrstor",Op_SrcMemNT }, // clobbers FP,MMX,SSE |
|---|
| 884 |
{ "fxsave", Op_DstMemNT }, |
|---|
| 885 |
{ "fxtract",Op_F0_P }, // pushes |
|---|
| 886 |
{ "fyl2x", Op_F0_P }, // pops |
|---|
| 887 |
{ "fyl2xp1",Op_F0_P }, // pops |
|---|
| 888 |
{ "haddpd", Op_DstSrcSSE }, |
|---|
| 889 |
{ "haddps", Op_DstSrcSSE }, |
|---|
| 890 |
{ "hlt", Op_0 }, |
|---|
| 891 |
{ "hsubpd", Op_DstSrcSSE }, |
|---|
| 892 |
{ "hsubps", Op_DstSrcSSE }, |
|---|
| 893 |
{ "idiv", Op_Src_DXAXF }, |
|---|
| 894 |
{ "imul", Op_DstSrcNT }, |
|---|
| 895 |
{ "in", Op_in }, |
|---|
| 896 |
{ "inc", Op_UpdF }, |
|---|
| 897 |
{ "ins", Op_ins }, |
|---|
| 898 |
{ "insb", Op_insX }, |
|---|
| 899 |
{ "insd", Op_insX }, |
|---|
| 900 |
{ "insw", Op_insX }, |
|---|
| 901 |
{ "int", Op_SrcImm }, |
|---|
| 902 |
{ "into", Op_0 }, |
|---|
| 903 |
{ "invd", Op_0 }, |
|---|
| 904 |
{ "invlpg", Op_SrcMemNT }, |
|---|
| 905 |
{ "iret", Op_iret }, |
|---|
| 906 |
{ "iretd", Op_iretd }, |
|---|
| 907 |
{ "iretq", Op_iretq }, |
|---|
| 908 |
{ "ja", Op_CBranch }, |
|---|
| 909 |
{ "jae", Op_CBranch }, |
|---|
| 910 |
{ "jb", Op_CBranch }, |
|---|
| 911 |
{ "jbe", Op_CBranch }, |
|---|
| 912 |
{ "jc", Op_CBranch }, |
|---|
| 913 |
{ "jcxz", Op_CBranch }, |
|---|
| 914 |
{ "je", Op_CBranch }, |
|---|
| 915 |
{ "jecxz", Op_CBranch }, |
|---|
| 916 |
{ "jg", Op_CBranch }, |
|---|
| 917 |
{ "jge", Op_CBranch }, |
|---|
| 918 |
{ "jl", Op_CBranch }, |
|---|
| 919 |
{ "jle", Op_CBranch }, |
|---|
| 920 |
{ "jmp", Op_Branch }, |
|---|
| 921 |
{ "jmpe", Op_Branch }, |
|---|
| 922 |
{ "jmpf", Op_Branch }, |
|---|
| 923 |
{ "jna", Op_CBranch }, |
|---|
| 924 |
{ "jnae", Op_CBranch }, |
|---|
| 925 |
{ "jnb", Op_CBranch }, |
|---|
| 926 |
{ "jnbe", Op_CBranch }, |
|---|
| 927 |
{ "jnc", Op_CBranch }, |
|---|
| 928 |
{ "jne", Op_CBranch }, |
|---|
| 929 |
{ "jng", Op_CBranch }, |
|---|
| 930 |
{ "jnge", Op_CBranch }, |
|---|
| 931 |
{ "jnl", Op_CBranch }, |
|---|
| 932 |
{ "jnle", Op_CBranch }, |
|---|
| 933 |
{ "jno", Op_CBranch }, |
|---|
| 934 |
{ "jnp", Op_CBranch }, |
|---|
| 935 |
{ "jns", Op_CBranch }, |
|---|
| 936 |
{ "jnz", Op_CBranch }, |
|---|
| 937 |
{ "jo", Op_CBranch }, |
|---|
| 938 |
{ "jp", Op_CBranch }, |
|---|
| 939 |
{ "jpe", Op_CBranch }, |
|---|
| 940 |
{ "jpo", Op_CBranch }, |
|---|
| 941 |
{ "jrcxz", Op_CBranch }, |
|---|
| 942 |
{ "js", Op_CBranch }, |
|---|
| 943 |
{ "jz", Op_CBranch }, |
|---|
| 944 |
{ "lahf", Op_0_AX }, |
|---|
| 945 |
{ "lar", Op_DstSrcFW }, // reg dest only |
|---|
| 946 |
{ "lddqu", Op_DstSrcSSE }, |
|---|
| 947 |
{ "ldmxcsr", Op_SrcMemNT }, |
|---|
| 948 |
{ "lds", Op_DstSrc }, // reg dest only |
|---|
| 949 |
{ "lea", Op_DstSrc }, // " |
|---|
| 950 |
{ "leaq", Op_DstSrcSSE }, // " |
|---|
| 951 |
{ "leave", Op_0 }, // EBP,ESP clobbers |
|---|
| 952 |
{ "lfence",Op_0 }, |
|---|
| 953 |
{ "lfs", Op_DstSrc }, |
|---|
| 954 |
{ "lgdt", Op_SrcMemNT }, |
|---|
| 955 |
{ "lgs", Op_DstSrc }, |
|---|
| 956 |
{ "lidt", Op_SrcMemNT }, |
|---|
| 957 |
{ "lldt", Op_SrcRMWNT }, |
|---|
| 958 |
{ "lmsw", Op_SrcRMWNT }, |
|---|
| 959 |
{ "lock", Op_0 }, |
|---|
| 960 |
{ "lods", Op_lods }, |
|---|
| 961 |
{ "lodsb", Op_lodsX }, |
|---|
| 962 |
{ "lodsd", Op_lodsX }, |
|---|
| 963 |
{ "lodsw", Op_lodsX }, |
|---|
| 964 |
{ "lodsq", Op_lodsX }, |
|---|
| 965 |
{ "loop", Op_Loop }, |
|---|
| 966 |
{ "loope", Op_Loop }, |
|---|
| 967 |
{ "loopne",Op_Loop }, |
|---|
| 968 |
{ "loopnz",Op_Loop }, |
|---|
| 969 |
{ "loopz", Op_Loop }, |
|---|
| 970 |
{ "lsl", Op_DstSrcFW }, // reg dest only |
|---|
| 971 |
{ "lss", Op_DstSrc }, |
|---|
| 972 |
{ "ltr", Op_DstMemNT }, |
|---|
| 973 |
{ "maskmovdqu", Op_SrcSrcMMX }, // writes to [edi] |
|---|
| 974 |
{ "maskmovq", Op_SrcSrcMMX }, |
|---|
| 975 |
{ "maxpd", Op_DstSrcSSE }, |
|---|
| 976 |
{ "maxps", Op_DstSrcSSE }, |
|---|
| 977 |
{ "maxsd", Op_DstSrcSSE }, |
|---|
| 978 |
{ "maxss", Op_DstSrcSSE }, |
|---|
| 979 |
{ "mfence",Op_0}, |
|---|
| 980 |
{ "minpd", Op_DstSrcSSE }, |
|---|
| 981 |
{ "minps", Op_DstSrcSSE }, |
|---|
| 982 |
{ "minsd", Op_DstSrcSSE }, |
|---|
| 983 |
{ "minss", Op_DstSrcSSE }, |
|---|
| 984 |
{ "monitor", Op_0 }, |
|---|
| 985 |
{ "mov", Op_DstSrc }, |
|---|
| 986 |
{ "movapd", Op_DstSrcSSE }, |
|---|
| 987 |
{ "movaps", Op_DstSrcSSE }, |
|---|
| 988 |
{ "movb", Op_DstSrcNT }, |
|---|
| 989 |
{ "movd", Op_DstSrcNT }, // also mmx and sse |
|---|
| 990 |
{ "movddup", Op_DstSrcSSE }, |
|---|
| 991 |
{ "movdq2q", Op_DstSrcNT }, // mmx/sse |
|---|
| 992 |
{ "movdqa", Op_DstSrcSSE }, |
|---|
| 993 |
{ "movdqu", Op_DstSrcSSE }, |
|---|
| 994 |
{ "movhlps", Op_DstSrcSSE }, |
|---|
| 995 |
{ "movhpd", Op_DstSrcSSE }, |
|---|
| 996 |
{ "movhps", Op_DstSrcSSE }, |
|---|
| 997 |
{ "movl", Op_DstSrc }, |
|---|
| 998 |
{ "movlhps", Op_DstSrcSSE }, |
|---|
| 999 |
{ "movlpd", Op_DstSrcSSE }, |
|---|
| 1000 |
{ "movlps", Op_DstSrcSSE }, |
|---|
| 1001 |
{ "movmskpd",Op_DstSrcSSE }, |
|---|
| 1002 |
{ "movmskps",Op_DstSrcSSE }, |
|---|
| 1003 |
{ "movntdq", Op_DstSrcNT }, // limited to sse, but mem dest |
|---|
| 1004 |
{ "movnti", Op_DstSrcNT }, // limited to gpr, but mem dest |
|---|
| 1005 |
{ "movntpd", Op_DstSrcNT }, // limited to sse, but mem dest |
|---|
| 1006 |
{ "movntps", Op_DstSrcNT }, // limited to sse, but mem dest |
|---|
| 1007 |
{ "movntq", Op_DstSrcNT }, // limited to mmx, but mem dest |
|---|
| 1008 |
{ "movq", Op_DstSrcNT }, // limited to sse and mmx |
|---|
| 1009 |
{ "movq2dq", Op_DstSrcNT }, // limited to sse <- mmx regs |
|---|
| 1010 |
{ "movs", Op_movs }, |
|---|
| 1011 |
{ "movsb", Op_movsX }, |
|---|
| 1012 |
{ "movsd", Op_movsd }, |
|---|
| 1013 |
{ "movsq", Op_movsd }, |
|---|
| 1014 |
{ "movshdup", Op_DstSrcSSE }, |
|---|
| 1015 |
{ "movsldup", Op_DstSrcSSE }, |
|---|
| 1016 |
{ "movss", Op_DstSrcSSE }, |
|---|
| 1017 |
{ "movsw", Op_movsX }, |
|---|
| 1018 |
{ "movsx", Op_movsx }, // word-only, reg dest |
|---|
| 1019 |
{ "movsxd", Op_movsx }, |
|---|
| 1020 |
{ "movupd",Op_DstSrcSSE }, |
|---|
| 1021 |
{ "movups",Op_DstSrcSSE }, |
|---|
| 1022 |
{ "movzbl", Op_DstSrcNT }, |
|---|
| 1023 |
{ "movzx", Op_movzx }, |
|---|
| 1024 |
{ "mul", Op_DstSrcNT }, |
|---|
| 1025 |
{ "mulpd", Op_DstSrcSSE }, |
|---|
| 1026 |
{ "mulps", Op_DstSrcSSE }, |
|---|
| 1027 |
{ "mulsd", Op_DstSrcSSE }, |
|---|
| 1028 |
{ "mulss", Op_DstSrcSSE }, |
|---|
| 1029 |
{ "mwait", Op_0 }, |
|---|
| 1030 |
{ "naked", Op_Naked }, |
|---|
| 1031 |
{ "neg", Op_UpdF }, |
|---|
| 1032 |
{ "nop", Op_0 }, |
|---|
| 1033 |
{ "not", Op_Upd }, |
|---|
| 1034 |
{ "or", Op_UpdSrcF }, |
|---|
| 1035 |
{ "orpd", Op_DstSrcSSE }, |
|---|
| 1036 |
{ "orps", Op_DstSrcSSE }, |
|---|
| 1037 |
{ "out", Op_out }, |
|---|
| 1038 |
{ "outs", Op_outs }, |
|---|
| 1039 |
{ "outsb", Op_outsX }, |
|---|
| 1040 |
{ "outsd", Op_outsX }, |
|---|
| 1041 |
{ "outsw", Op_outsX }, |
|---|
| 1042 |
{ "pabsb", Op_DstSrcSSE }, |
|---|
| 1043 |
{ "pabsw", Op_DstSrcSSE }, |
|---|
| 1044 |
{ "pabsq", Op_DstSrcSSE }, |
|---|
| 1045 |
{ "packssdw", Op_DstSrcMMX }, // %% also SSE |
|---|
| 1046 |
{ "packsswb", Op_DstSrcMMX }, |
|---|
| 1047 |
{ "packuswb", Op_DstSrcMMX }, |
|---|
| 1048 |
{ "paddb", Op_DstSrcMMX }, |
|---|
| 1049 |
{ "paddd", Op_DstSrcMMX }, |
|---|
| 1050 |
{ "paddq", Op_DstSrcMMX }, |
|---|
| 1051 |
{ "paddsb", Op_DstSrcMMX }, |
|---|
| 1052 |
{ "paddsw", Op_DstSrcMMX }, |
|---|
| 1053 |
{ "paddusb", Op_DstSrcMMX }, |
|---|
| 1054 |
{ "paddusw", Op_DstSrcMMX }, |
|---|
| 1055 |
{ "paddw", Op_DstSrcMMX }, |
|---|
| 1056 |
{ "palignr", Op_DstSrcSSE }, |
|---|
| 1057 |
{ "pand", Op_DstSrcMMX }, |
|---|
| 1058 |
{ "pandn", Op_DstSrcMMX }, |
|---|
| 1059 |
{ "pause", Op_DstSrcMMX }, |
|---|
| 1060 |
{ "pavgb", Op_DstSrcMMX }, |
|---|
| 1061 |
{ "pavgw", Op_DstSrcMMX }, |
|---|
| 1062 |
{ "pcmpeqb", Op_DstSrcMMX }, |
|---|
| 1063 |
{ "pcmpeqd", Op_DstSrcMMX }, |
|---|
| 1064 |
{ "pcmpeqw", Op_DstSrcMMX }, |
|---|
| 1065 |
{ "pcmpgtb", Op_DstSrcMMX }, |
|---|
| 1066 |
{ "pcmpgtd", Op_DstSrcMMX }, |
|---|
| 1067 |
{ "pcmpgtw", Op_DstSrcMMX }, |
|---|
| 1068 |
{ "pextrw", Op_DstSrcImmM }, // gpr32 dest |
|---|
| 1069 |
{ "phaddd", Op_DstSrcSSE }, |
|---|
| 1070 |
{ "phaddsw", Op_DstSrcSSE }, |
|---|
| 1071 |
{ "phaddw", Op_DstSrcSSE }, |
|---|
| 1072 |
{ "phsubd", Op_DstSrcSSE }, |
|---|
| 1073 |
{ "phsubsw", Op_DstSrcSSE }, |
|---|
| 1074 |
{ "phsubw", Op_DstSrcSSE }, |
|---|
| 1075 |
{ "pinsrw", Op_DstSrcImmM }, // gpr32(16), mem16 src, sse too |
|---|
| 1076 |
{ "pmaddubsw", Op_DstSrcSSE }, |
|---|
| 1077 |
{ "pmaddwd", Op_DstSrcMMX }, |
|---|
| 1078 |
{ "pmaxsw", Op_DstSrcMMX }, |
|---|
| 1079 |
{ "pmaxub", Op_DstSrcMMX }, |
|---|
| 1080 |
{ "pminsw", Op_DstSrcMMX }, |
|---|
| 1081 |
{ "pminub", Op_DstSrcMMX }, |
|---|
| 1082 |
{ "pmovmskb", Op_DstSrcMMX }, |
|---|
| 1083 |
{ "pmulhrsw", Op_DstSrcMMX }, |
|---|
| 1084 |
{ "pmulhuw", Op_DstSrcMMX }, |
|---|
| 1085 |
{ "pmulhw", Op_DstSrcMMX }, |
|---|
| 1086 |
{ "pmullw", Op_DstSrcMMX }, |
|---|
| 1087 |
{ "pmuludq", Op_DstSrcMMX }, // also sse |
|---|
| 1088 |
{ "popf", Op_SizedStack }, // rewrite the insn with a special case |
|---|
| 1089 |
{ "popfq", Op_SizedStack }, |
|---|
| 1090 |
{ "popq", Op_push }, |
|---|
| 1091 |
{ "por", Op_DstSrcMMX }, |
|---|
| 1092 |
{ "prefetchnta", Op_SrcMemNT }, |
|---|
| 1093 |
{ "prefetcht0", Op_SrcMemNT }, |
|---|
| 1094 |
{ "prefetcht1", Op_SrcMemNT }, |
|---|
| 1095 |
{ "prefetcht2", Op_SrcMemNT }, |
|---|
| 1096 |
{ "psadbw", Op_DstSrcMMX }, |
|---|
| 1097 |
{ "pshufb", Op_DstSrcImmM }, |
|---|
| 1098 |
{ "pshufd", Op_DstSrcImmM }, |
|---|
| 1099 |
{ "pshufhw", Op_DstSrcImmM }, |
|---|
| 1100 |
{ "pshuflw", Op_DstSrcImmM }, |
|---|
| 1101 |
{ "pshufw", Op_DstSrcImmM }, |
|---|
| 1102 |
{ "psignb", Op_DstSrcSSE }, |
|---|
| 1103 |
{ "psignd", Op_DstSrcSSE }, |
|---|
| 1104 |
{ "psignw", Op_DstSrcSSE }, |
|---|
| 1105 |
{ "pslld", Op_DstSrcMMX }, // immediate operands... |
|---|
| 1106 |
{ "pslldq", Op_DstSrcMMX }, |
|---|
| 1107 |
{ "psllq", Op_DstSrcMMX }, |
|---|
| 1108 |
{ "psllw", Op_DstSrcMMX }, |
|---|
| 1109 |
{ "psrad", Op_DstSrcMMX }, |
|---|
| 1110 |
{ "psraw", Op_DstSrcMMX }, |
|---|
| 1111 |
{ "psrld", Op_DstSrcMMX }, |
|---|
| 1112 |
{ "psrldq", Op_DstSrcMMX }, |
|---|
| 1113 |
{ "psrlq", Op_DstSrcMMX }, |
|---|
| 1114 |
{ "psrlw", Op_DstSrcMMX }, |
|---|
| 1115 |
{ "psubb", Op_DstSrcMMX }, |
|---|
| 1116 |
{ "psubd", Op_DstSrcMMX }, |
|---|
| 1117 |
{ "psubq", Op_DstSrcMMX }, |
|---|
| 1118 |
{ "psubsb", Op_DstSrcMMX }, |
|---|
| 1119 |
{ "psubsw", Op_DstSrcMMX }, |
|---|
| 1120 |
{ "psubusb", Op_DstSrcMMX }, |
|---|
| 1121 |
{ "psubusw", Op_DstSrcMMX }, |
|---|
| 1122 |
{ "psubw", Op_DstSrcMMX }, |
|---|
| 1123 |
{ "punpckhbw", Op_DstSrcMMX }, |
|---|
| 1124 |
{ "punpckhdq", Op_DstSrcMMX }, |
|---|
| 1125 |
{ "punpckhqdq",Op_DstSrcMMX }, |
|---|
| 1126 |
{ "punpckhwd", Op_DstSrcMMX }, |
|---|
| 1127 |
{ "punpcklbw", Op_DstSrcMMX }, |
|---|
| 1128 |
{ "punpckldq", Op_DstSrcMMX }, |
|---|
| 1129 |
{ "punpcklqdq",Op_DstSrcMMX }, |
|---|
| 1130 |
{ "punpcklwd", Op_DstSrcMMX }, |
|---|
| 1131 |
{ "pushf", Op_SizedStack }, |
|---|
| 1132 |
{ "pushfq", Op_SizedStack }, |
|---|
| 1133 |
{ "pushq", Op_push }, |
|---|
| 1134 |
{ "pxor", Op_DstSrcMMX }, |
|---|
| 1135 |
{ "rcl", Op_Shift }, // limited src operands -- change to shift |
|---|
| 1136 |
{ "rcpps", Op_DstSrcSSE }, |
|---|
| 1137 |
{ "rcpss", Op_DstSrcSSE }, |
|---|
| 1138 |
{ "rcr", Op_Shift }, |
|---|
| 1139 |
{ "rdmsr", Op_0_DXAX }, |
|---|
| 1140 |
{ "rdpmc", Op_0_DXAX }, |
|---|
| 1141 |
{ "rdtsc", Op_0_DXAX }, |
|---|
| 1142 |
{ "rep", Op_0 }, |
|---|
| 1143 |
{ "repe", Op_0 }, |
|---|
| 1144 |
{ "repne", Op_0 }, |
|---|
| 1145 |
{ "repnz", Op_0 }, |
|---|
| 1146 |
{ "repz", Op_0 }, |
|---|
| 1147 |
{ "ret", Op_ret }, |
|---|
| 1148 |
{ "retf", Op_retf }, |
|---|
| 1149 |
{ "retn", Op_retf }, |
|---|
| 1150 |
{ "rol", Op_Shift }, |
|---|
| 1151 |
{ "ror", Op_Shift }, |
|---|
| 1152 |
{ "rsm", Op_0 }, |
|---|
| 1153 |
{ "rsqrtps", Op_DstSrcSSE }, |
|---|
| 1154 |
{ "rsqrtss", Op_DstSrcSSE }, |
|---|
| 1155 |
{ "sahf", Op_Flags }, |
|---|
| 1156 |
{ "sal", Op_Shift }, |
|---|
| 1157 |
{ "salq", Op_DstSrcNT }, |
|---|
| 1158 |
{ "sar", Op_Shift }, |
|---|
| 1159 |
{ "sbb", Op_UpdSrcF }, |
|---|
| 1160 |
{ "scas", Op_scas }, |
|---|
| 1161 |
{ "scasb", Op_scasX }, |
|---|
| 1162 |
{ "scasd", Op_scasX }, |
|---|
| 1163 |
{ "scasw", Op_scasX }, |
|---|
| 1164 |
{ "scasq", Op_scasX }, |
|---|
| 1165 |
{ "seta", Op_DstRMBNT }, // also gpr8 |
|---|
| 1166 |
{ "setae", Op_DstRMBNT }, |
|---|
| 1167 |
{ "setb", Op_DstRMBNT }, |
|---|
| 1168 |
{ "setbe", Op_DstRMBNT }, |
|---|
| 1169 |
{ "setc", Op_DstRMBNT }, |
|---|
| 1170 |
{ "sete", Op_DstRMBNT }, |
|---|
| 1171 |
{ "setg", Op_DstRMBNT }, |
|---|
| 1172 |
{ "setge", Op_DstRMBNT }, |
|---|
| 1173 |
{ "setl", Op_DstRMBNT }, |
|---|
| 1174 |
{ "setle", Op_DstRMBNT }, |
|---|
| 1175 |
{ "setna", Op_DstRMBNT }, |
|---|
| 1176 |
{ "setnae", Op_DstRMBNT }, |
|---|
| 1177 |
{ "setnb", Op_DstRMBNT }, |
|---|
| 1178 |
{ "setnbe", Op_DstRMBNT }, |
|---|
| 1179 |
{ "setnc", Op_DstRMBNT }, |
|---|
| 1180 |
{ "setne", Op_DstRMBNT }, |
|---|
| 1181 |
{ "setng", Op_DstRMBNT }, |
|---|
| 1182 |
{ "setnge", Op_DstRMBNT }, |
|---|
| 1183 |
{ "setnl", Op_DstRMBNT }, |
|---|
| 1184 |
{ "setnle", Op_DstRMBNT }, |
|---|
| 1185 |
{ "setno", Op_DstRMBNT }, |
|---|
| 1186 |
{ "setnp", Op_DstRMBNT }, |
|---|
| 1187 |
{ "setns", Op_DstRMBNT }, |
|---|
| 1188 |
{ "setnz", Op_DstRMBNT }, |
|---|
| 1189 |
{ "seto", Op_DstRMBNT }, |
|---|
| 1190 |
{ "setp", Op_DstRMBNT }, |
|---|
| 1191 |
{ "setpe", Op_DstRMBNT }, |
|---|
| 1192 |
{ "setpo", Op_DstRMBNT }, |
|---|
| 1193 |
{ "sets", Op_DstRMBNT }, |
|---|
| 1194 |
{ "setz", Op_DstRMBNT }, |
|---|
| 1195 |
{ "sfence", Op_0 }, |
|---|
| 1196 |
{ "sgdt", Op_DstMemNT }, |
|---|
| 1197 |
{ "shl", Op_Shift }, |
|---|
| 1198 |
{ "shld", Op_UpdSrcShft }, |
|---|
| 1199 |
{ "shr", Op_Shift }, |
|---|
| 1200 |
{ "shrd", Op_UpdSrcShft }, |
|---|
| 1201 |
{ "shufpd", Op_DstSrcImmS }, |
|---|
| 1202 |
{ "shufps", Op_DstSrcImmS }, |
|---|
| 1203 |
{ "sidt", Op_DstMemNT }, |
|---|
| 1204 |
{ "sldt", Op_DstRMWNT }, |
|---|
| 1205 |
{ "smsw", Op_DstRMWNT }, |
|---|
| 1206 |
{ "sqrtpd", Op_DstSrcSSE }, |
|---|
| 1207 |
{ "sqrtps", Op_DstSrcSSE }, |
|---|
| 1208 |
{ "sqrtsd", Op_DstSrcSSE }, |
|---|
| 1209 |
{ "sqrtss", Op_DstSrcSSE }, |
|---|
| 1210 |
{ "stc", Op_Flags }, |
|---|
| 1211 |
{ "std", Op_Flags }, |
|---|
| 1212 |
{ "sti", Op_Flags }, |
|---|
| 1213 |
{ "stmxcsr",Op_DstMemNT }, |
|---|
| 1214 |
{ "stos", Op_stos }, |
|---|
| 1215 |
{ "stosb", Op_stosX }, |
|---|
| 1216 |
{ "stosd", Op_stosX }, |
|---|
| 1217 |
{ "stosw", Op_stosX }, |
|---|
| 1218 |
{ "stosq", Op_stosX }, |
|---|
| 1219 |
{ "str", Op_DstMemNT }, // also r16 |
|---|
| 1220 |
{ "sub", Op_UpdSrcF }, |
|---|
| 1221 |
{ "subpd", Op_DstSrcSSE }, |
|---|
| 1222 |
{ "subps", Op_DstSrcSSE }, |
|---|
| 1223 |
{ "subq", Op_DstSrcSSE }, |
|---|
| 1224 |
{ "subsd", Op_DstSrcSSE }, |
|---|
| 1225 |
{ "subss", Op_DstSrcSSE }, |
|---|
| 1226 |
{ "swapgs", Op_DstSrcSSE }, |
|---|
| 1227 |
{ "syscall", Op_0 }, |
|---|
| 1228 |
{ "sysenter",Op_0 }, |
|---|
| 1229 |
{ "sysexit", Op_0 }, |
|---|
| 1230 |
{ "sysret", Op_0 }, |
|---|
| 1231 |
{ "sysretq", Op_0 }, |
|---|
| 1232 |
{ "test", Op_SrcSrcF }, |
|---|
| 1233 |
{ "ucomisd", Op_SrcSrcSSEF }, |
|---|
| 1234 |
{ "ucomiss", Op_SrcSrcSSEF }, |
|---|
| 1235 |
{ "ud2", Op_0 }, |
|---|
| 1236 |
{ "unpckhpd", Op_DstSrcSSE }, |
|---|
| 1237 |
{ "unpckhps", Op_DstSrcSSE }, |
|---|
| 1238 |
{ "unpcklpd", Op_DstSrcSSE }, |
|---|
| 1239 |
{ "unpcklps", Op_DstSrcSSE }, |
|---|
| 1240 |
{ "verr", Op_SrcMemNTF }, |
|---|
| 1241 |
{ "verw", Op_SrcMemNTF }, |
|---|
| 1242 |
{ "wbinvd", Op_0 }, |
|---|
| 1243 |
{ "wrmsr", Op_0 }, |
|---|
| 1244 |
{ "xadd", Op_UpdUpdF }, |
|---|
| 1245 |
{ "xchg", Op_UpdUpd }, |
|---|
| 1246 |
{ "xlat", Op_xlat }, |
|---|
| 1247 |
{ "xlatb", Op_0_AX }, |
|---|
| 1248 |
{ "xor", Op_DstSrcF }, |
|---|
| 1249 |
{ "xorpd", Op_DstSrcSSE }, |
|---|
| 1250 |
{ "xorps", Op_DstSrcSSE }, |
|---|
| 1251 |
{ "xorq", Op_DstSrcNT }, |
|---|
| 1252 |
}; |
|---|
| 1253 |
|
|---|
| 1254 |
typedef enum |
|---|
| 1255 |
{ |
|---|
| 1256 |
Default_Ptr = 0, |
|---|
| 1257 |
Byte_Ptr = 1, |
|---|
| 1258 |
Short_Ptr = 2, |
|---|
| 1259 |
Int_Ptr = 4, |
|---|
| 1260 |
QWord_Ptr = 8, |
|---|
| 1261 |
Float_Ptr = 4, |
|---|
| 1262 |
Double_Ptr = 8, |
|---|
| 1263 |
Extended_Ptr = 10, |
|---|
| 1264 |
Near_Ptr = 98, |
|---|
| 1265 |
Far_Ptr = 99, |
|---|
| 1266 |
N_PtrTypes |
|---|
| 1267 |
} PtrType; |
|---|
| 1268 |
|
|---|
| 1269 |
static const int N_PtrNames = 8; |
|---|
| 1270 |
static const char * ptrTypeNameTable[N_PtrNames] = |
|---|
| 1271 |
{ |
|---|
| 1272 |
"word", "dword", "qword", |
|---|
| 1273 |
"float", "double", "extended", |
|---|
| 1274 |
"near", "far" |
|---|
| 1275 |
}; |
|---|
| 1276 |
|
|---|
| 1277 |
static Identifier * ptrTypeIdentTable[N_PtrNames]; |
|---|
| 1278 |
static PtrType ptrTypeValueTable[N_PtrNames] = |
|---|
| 1279 |
{ |
|---|
| 1280 |
Short_Ptr, Int_Ptr, QWord_Ptr, |
|---|
| 1281 |
Float_Ptr, Double_Ptr, Extended_Ptr, |
|---|
| 1282 |
Near_Ptr, Far_Ptr |
|---|
| 1283 |
}; |
|---|
| 1284 |
|
|---|
| 1285 |
typedef enum |
|---|
| 1286 |
{ |
|---|
| 1287 |
Opr_Invalid, |
|---|
| 1288 |
Opr_Immediate, |
|---|
| 1289 |
Opr_Reg, |
|---|
| 1290 |
Opr_Mem |
|---|
| 1291 |
} OperandClass; |
|---|
| 1292 |
|
|---|
| 1293 |
/* kill inlining if we reference a local? */ |
|---|
| 1294 |
|
|---|
| 1295 |
/* DMD seems to allow only one 'symbol' per operand .. include __LOCAL_SIZE */ |
|---|
| 1296 |
|
|---|
| 1297 |
/* DMD offset usage: <parm>[<reg>] seems to always be relative to EBP+8 .. even |
|---|
| 1298 |
if naked.. */ |
|---|
| 1299 |
|
|---|
| 1300 |
// mov eax, 4 |
|---|
| 1301 |
// mov eax, fs:4 |
|---|
| 1302 |
// -- have to assume we know whether or not to use '$' |
|---|
| 1303 |
|
|---|
| 1304 |
static Token eof_tok; |
|---|
| 1305 |
static Expression * Handled; |
|---|
| 1306 |
static Identifier * ident_seg; |
|---|
| 1307 |
|
|---|
| 1308 |
struct AsmProcessor |
|---|
| 1309 |
{ |
|---|
| 1310 |
typedef struct |
|---|
| 1311 |
{ |
|---|
| 1312 |
int inBracket; |
|---|
| 1313 |
int hasBracket; |
|---|
| 1314 |
int hasNumber; |
|---|
| 1315 |
int isOffset; |
|---|
| 1316 |
|
|---|
| 1317 |
Reg segmentPrefix; |
|---|
| 1318 |
Reg reg; |
|---|
| 1319 |
sinteger_t constDisplacement; // use to build up.. should be int constant in the end.. |
|---|
| 1320 |
Array symbolDisplacement; // array of expressions or.. |
|---|
| 1321 |
Reg baseReg; |
|---|
| 1322 |
Reg indexReg; |
|---|
| 1323 |
int scale; |
|---|
| 1324 |
|
|---|
| 1325 |
OperandClass cls; |
|---|
| 1326 |
PtrType dataSize; |
|---|
| 1327 |
PtrType dataSizeHint; // DMD can use the type of a referenced variable |
|---|
| 1328 |
} Operand; |
|---|
| 1329 |
|
|---|
| 1330 |
static const unsigned Max_Operands = 3; |
|---|
| 1331 |
|
|---|
| 1332 |
AsmStatement * stmt; |
|---|
| 1333 |
Scope * sc; |
|---|
| 1334 |
|
|---|
| 1335 |
Token * token; |
|---|
| 1336 |
std::ostringstream insnTemplate; |
|---|
| 1337 |
|
|---|
| 1338 |
AsmOp op; |
|---|
| 1339 |
AsmOpInfo * opInfo; |
|---|
| 1340 |
Operand operands[Max_Operands]; |
|---|
| 1341 |
Identifier * opIdent; |
|---|
| 1342 |
Operand * operand; |
|---|
| 1343 |
|
|---|
| 1344 |
AsmProcessor ( Scope * sc, AsmStatement * stmt ) |
|---|
| 1345 |
{ |
|---|
| 1346 |
this->sc = sc; |
|---|
| 1347 |
this->stmt = stmt; |
|---|
| 1348 |
token = stmt->tokens; |
|---|
| 1349 |
|
|---|
| 1350 |
opInfo = NULL; |
|---|
| 1351 |
|
|---|
| 1352 |
if ( ! regInfo[0].ident ) |
|---|
| 1353 |
{ |
|---|
| 1354 |
char buf[8], *p; |
|---|
| 1355 |
|
|---|
| 1356 |
for ( int i = 0; i < N_Regs; i++ ) |
|---|
| 1357 |
{ |
|---|
| 1358 |
strncpy ( buf, regInfo[i].name, sizeof ( buf ) - 1 ); |
|---|
| 1359 |
for ( p = buf; *p; p++ ) |
|---|
| 1360 |
*p = std::tolower ( *p ); |
|---|
| 1361 |
regInfo[i].gccName = std::string ( buf, p - buf ); |
|---|
| 1362 |
if ( ( i <= Reg_ST || i > Reg_ST7 ) && i != Reg_EFLAGS ) |
|---|
| 1363 |
regInfo[i].ident = Lexer::idPool ( regInfo[i].name ); |
|---|
| 1364 |
} |
|---|
| 1365 |
|
|---|
| 1366 |
for ( int i = 0; i < N_PtrNames; i++ ) |
|---|
| 1367 |
ptrTypeIdentTable[i] = Lexer::idPool ( ptrTypeNameTable[i] ); |
|---|
| 1368 |
|
|---|
| 1369 |
Handled = new Expression ( 0, TOKvoid, sizeof ( Expression ) ); |
|---|
| 1370 |
|
|---|
| 1371 |
ident_seg = Lexer::idPool ( "seg" ); |
|---|
| 1372 |
|
|---|
| 1373 |
eof_tok.value = TOKeof; |
|---|
| 1374 |
eof_tok.next = 0; |
|---|
| 1375 |
} |
|---|
| 1376 |
} |
|---|
| 1377 |
|
|---|
| 1378 |
void run() |
|---|
| 1379 |
{ |
|---|
| 1380 |
parse(); |
|---|
| 1381 |
} |
|---|
| 1382 |
|
|---|
| 1383 |
void nextToken() |
|---|
| 1384 |
{ |
|---|
| 1385 |
if ( token->next ) |
|---|
| 1386 |
token = token->next; |
|---|
| 1387 |
else |
|---|
| 1388 |
token = & eof_tok; |
|---|
| 1389 |
} |
|---|
| 1390 |
|
|---|
| 1391 |
Token * peekToken() |
|---|
| 1392 |
{ |
|---|
| 1393 |
if ( token->next ) |
|---|
| 1394 |
return token->next; |
|---|
| 1395 |
else |
|---|
| 1396 |
return & eof_tok; |
|---|
| 1397 |
} |
|---|
| 1398 |
|
|---|
| 1399 |
void expectEnd() |
|---|
| 1400 |
{ |
|---|
| 1401 |
if ( token->value != TOKeof ) |
|---|
| 1402 |
stmt->error ( "expected end of statement" ); // %% extra at end... |
|---|
| 1403 |
} |
|---|
| 1404 |
|
|---|
| 1405 |
void parse() |
|---|
| 1406 |
{ |
|---|
| 1407 |
op = parseOpcode(); |
|---|
| 1408 |
|
|---|
| 1409 |
switch ( op ) |
|---|
| 1410 |
{ |
|---|
| 1411 |
case Op_Align: |
|---|
| 1412 |
doAlign(); |
|---|
| 1413 |
expectEnd(); |
|---|
| 1414 |
break; |
|---|
| 1415 |
case Op_Even: |
|---|
| 1416 |
doEven(); |
|---|
| 1417 |
expectEnd(); |
|---|
| 1418 |
break; |
|---|
| 1419 |
case Op_Naked: |
|---|
| 1420 |
doNaked(); |
|---|
| 1421 |
expectEnd(); |
|---|
| 1422 |
break; |
|---|
| 1423 |
case Op_Invalid: |
|---|
| 1424 |
break; |
|---|
| 1425 |
default: |
|---|
| 1426 |
if ( op >= Op_db && op <= Op_de ) |
|---|
| 1427 |
doData(); |
|---|
| 1428 |
else |
|---|
| 1429 |
doInstruction(); |
|---|
| 1430 |
} |
|---|
| 1431 |
} |
|---|
| 1432 |
|
|---|
| 1433 |
AsmOp parseOpcode() |
|---|
| 1434 |
{ |
|---|
| 1435 |
static const int N_ents = sizeof ( opData ) /sizeof ( AsmOpEnt ); |
|---|
| 1436 |
|
|---|
| 1437 |
switch ( token->value ) |
|---|
| 1438 |
{ |
|---|
| 1439 |
case TOKalign: |
|---|
| 1440 |
nextToken(); |
|---|
| 1441 |
return Op_Align; |
|---|
| 1442 |
case TOKin: |
|---|
| 1443 |
nextToken(); |
|---|
| 1444 |
opIdent = Id::___in; |
|---|
| 1445 |
return Op_in; |
|---|
| 1446 |
case TOKint32: // "int" |
|---|
| 1447 |
nextToken(); |
|---|
| 1448 |
opIdent = Id::__int; |
|---|
| 1449 |
return Op_SrcImm; |
|---|
| 1450 |
case TOKout: |
|---|
| 1451 |
nextToken(); |
|---|
| 1452 |
opIdent = Id::___out; |
|---|
| 1453 |
return Op_out; |
|---|
| 1454 |
case TOKidentifier: |
|---|
| 1455 |
// search for mnemonic below |
|---|
| 1456 |
break; |
|---|
| 1457 |
default: |
|---|
| 1458 |
stmt->error ( "expected opcode" ); |
|---|
| 1459 |
return Op_Invalid; |
|---|
| 1460 |
} |
|---|
| 1461 |
|
|---|
| 1462 |
opIdent = token->ident; |
|---|
| 1463 |
const char * opcode = token->ident->string; |
|---|
| 1464 |
|
|---|
| 1465 |
nextToken(); |
|---|
| 1466 |
|
|---|
| 1467 |
// %% okay to use bsearch? |
|---|
| 1468 |
int i = 0, j = N_ents, k, l; |
|---|
| 1469 |
do |
|---|
| 1470 |
{ |
|---|
| 1471 |
k = ( i + j ) / 2; |
|---|
| 1472 |
l = strcmp ( opcode, opData[k].inMnemonic ); |
|---|
| 1473 |
if ( ! l ) |
|---|
| 1474 |
return opData[k].asmOp; |
|---|
| 1475 |
else if ( l < 0 ) |
|---|
| 1476 |
j = k; |
|---|
| 1477 |
else |
|---|
| 1478 |
i = k + 1; |
|---|
| 1479 |
} |
|---|
| 1480 |
while ( i != j ); |
|---|
| 1481 |
|
|---|
| 1482 |
stmt->error ( "unknown opcode '%s'", opcode ); |
|---|
| 1483 |
|
|---|
| 1484 |
return Op_Invalid; |
|---|
| 1485 |
} |
|---|
| 1486 |
|
|---|
| 1487 |
// need clobber information.. use information is good too... |
|---|
| 1488 |
void doInstruction() |
|---|
| 1489 |
{ |
|---|
| 1490 |
bool ok = true; |
|---|
| 1491 |
unsigned operand_i = 0; |
|---|
| 1492 |
|
|---|
| 1493 |
opInfo = & asmOpInfo[op]; |
|---|
| 1494 |
memset ( operands, 0, sizeof ( operands ) ); |
|---|
| 1495 |
|
|---|
| 1496 |
if ( token->value == TOKeof && ( op == Op_FMath0) ) |
|---|
| 1497 |
{ |
|---|
| 1498 |
for ( operand_i = 0; operand_i < 1; operand_i++) |
|---|
| 1499 |
{ |
|---|
| 1500 |
operand = & operands[operand_i]; |
|---|
| 1501 |
operand->reg = operand->baseReg = operand->indexReg = |
|---|
| 1502 |
operand->segmentPrefix = Reg_Invalid; |
|---|
| 1503 |
|
|---|
| 1504 |
operand->cls = Opr_Reg; |
|---|
| 1505 |
if ( operand_i == 0) |
|---|
| 1506 |
{ |
|---|
| 1507 |
operand->reg = Reg_ST; |
|---|
| 1508 |
} |
|---|
| 1509 |
else |
|---|
| 1510 |
{ |
|---|
| 1511 |
operand->reg = Reg_ST1; |
|---|
| 1512 |
} |
|---|
| 1513 |
operand->hasNumber = 0; |
|---|
| 1514 |
operand->constDisplacement = 0; |
|---|
| 1515 |
parseOperand(); |
|---|
| 1516 |
|
|---|
| 1517 |
if ( matchOperands ( operand_i ) ) |
|---|
| 1518 |
{ |
|---|
| 1519 |
AsmCode * asmcode = new AsmCode ( N_Regs ); |
|---|
| 1520 |
|
|---|
| 1521 |
if ( formatInstruction ( operand_i, asmcode ) ) |
|---|
| 1522 |
stmt->asmcode = ( code * ) asmcode; |
|---|
| 1523 |
} |
|---|
| 1524 |
} |
|---|
| 1525 |
return; |
|---|
| 1526 |
} |
|---|
| 1527 |
|
|---|
| 1528 |
while ( token->value != TOKeof ) |
|---|
| 1529 |
{ |
|---|
| 1530 |
if ( operand_i < Max_Operands ) |
|---|
| 1531 |
{ |
|---|
| 1532 |
operand = & operands[operand_i]; |
|---|
| 1533 |
operand->reg = operand->baseReg = operand->indexReg = |
|---|
| 1534 |
operand->segmentPrefix = Reg_Invalid; |
|---|
| 1535 |
parseOperand(); |
|---|
| 1536 |
operand_i++; |
|---|
| 1537 |
} |
|---|
| 1538 |
else |
|---|
| 1539 |
{ |
|---|
| 1540 |
ok = false; |
|---|
| 1541 |
stmt->error ( "too many operands for instruction" ); |
|---|
| 1542 |
break; |
|---|
| 1543 |
} |
|---|
| 1544 |
|
|---|
| 1545 |
if ( token->value == TOKcomma ) |
|---|
| 1546 |
{ |
|---|
| 1547 |
nextToken(); |
|---|
| 1548 |
} |
|---|
| 1549 |
else if ( token->value != TOKeof ) |
|---|
| 1550 |
{ |
|---|
| 1551 |
ok = false; |
|---|
| 1552 |
stmt->error ( "expected comma after operand" ); |
|---|
| 1553 |
return; |
|---|
| 1554 |
} |
|---|
| 1555 |
} |
|---|
| 1556 |
// if (operand_i < opInfo->minOperands) { |
|---|
| 1557 |
// ok = false; |
|---|
| 1558 |
// stmt->error("too few operands for instruction"); |
|---|
| 1559 |
// } |
|---|
| 1560 |
|
|---|
| 1561 |
if ( matchOperands ( operand_i ) ) |
|---|
| 1562 |
{ |
|---|
| 1563 |
AsmCode * asmcode = new AsmCode ( N_Regs ); |
|---|
| 1564 |
|
|---|
| 1565 |
if ( formatInstruction ( operand_i, asmcode ) ) |
|---|
| 1566 |
stmt->asmcode = ( code * ) asmcode; |
|---|
| 1567 |
} |
|---|
| 1568 |
} |
|---|
| 1569 |
|
|---|
| 1570 |
void setAsmCode() |
|---|
| 1571 |
{ |
|---|
| 1572 |
AsmCode * asmcode = new AsmCode ( N_Regs ); |
|---|
| 1573 |
asmcode->insnTemplate = insnTemplate.str(); |
|---|
| 1574 |
Logger::cout() << "insnTemplate = " << asmcode->insnTemplate << '\n'; |
|---|
| 1575 |
stmt->asmcode = ( code* ) asmcode; |
|---|
| 1576 |
} |
|---|
| 1577 |
|
|---|
| 1578 |
// note: doesn't update AsmOp op |
|---|
| 1579 |
bool matchOperands ( unsigned nOperands ) |
|---|
| 1580 |
{ |
|---|
| 1581 |
bool wrong_number = true; |
|---|
| 1582 |
|
|---|
| 1583 |
for ( unsigned i = 0; i < nOperands; i++ ) |
|---|
| 1584 |
classifyOperand ( & operands[i] ); |
|---|
| 1585 |
|
|---|
| 1586 |
while ( 1 ) |
|---|
| 1587 |
{ |
|---|
| 1588 |
if ( nOperands == opInfo->nOperands() ) |
|---|
| 1589 |
{ |
|---|
| 1590 |
wrong_number = false; |
|---|
| 1591 |
/* Cases in which number of operands is not |
|---|
| 1592 |
enough for a match: Op_FCmp/Op_FCmp1, |
|---|
| 1593 |
Op_FCmpP/Op_FCmpP1 */ |
|---|
| 1594 |
for ( unsigned i = 0; i < nOperands; i++ ) |
|---|
| 1595 |
{ |
|---|
| 1596 |
Operand * operand = & operands[i]; |
|---|
| 1597 |
|
|---|
| 1598 |
switch ( opInfo->operands[i] & Opr_ClassMask ) |
|---|
| 1599 |
{ |
|---|
| 1600 |
case OprC_Mem: // no FPMem currently |
|---|
| 1601 |
if ( operand->cls != Opr_Mem ) |
|---|
| 1602 |
goto no_match; |
|---|
| 1603 |
break; |
|---|
| 1604 |
case OprC_RFP: |
|---|
| 1605 |
if ( ! ( operand->reg >= Reg_ST && operand->reg <= Reg_ST7 ) ) |
|---|
| 1606 |
goto no_match; |
|---|
| 1607 |
break; |
|---|
| 1608 |
default: |
|---|
| 1609 |
break; |
|---|
| 1610 |
} |
|---|
| 1611 |
} |
|---|
| 1612 |
|
|---|
| 1613 |
return true; |
|---|
| 1614 |
} |
|---|
| 1615 |
no_match: |
|---|
| 1616 |
if ( opInfo->linkType == Next_Form ) |
|---|
| 1617 |
opInfo = & asmOpInfo[ op = ( AsmOp ) opInfo->link ]; |
|---|
| 1618 |
else |
|---|
| 1619 |
break; |
|---|
| 1620 |
} |
|---|
| 1621 |
if ( wrong_number ) |
|---|
| 1622 |
stmt->error ( "wrong number of operands" ); |
|---|
| 1623 |
else |
|---|
| 1624 |
stmt->error ( "wrong operand types" ); |
|---|
| 1625 |
return false; |
|---|
| 1626 |
} |
|---|
| 1627 |
|
|---|
| 1628 |
void addOperand ( const char * fmt, AsmArgType type, Expression * e, AsmCode * asmcode, AsmArgMode mode = Mode_Input ) |
|---|
| 1629 |
{ |
|---|
| 1630 |
if ( sc->func->naked ) |
|---|
| 1631 |
{ |
|---|
| 1632 |
switch ( type ) |
|---|
| 1633 |
{ |
|---|
| 1634 |
case Arg_Integer: |
|---|
| 1635 |
if ( e->type->isunsigned() ) |
|---|
| 1636 |
insnTemplate << "$" << e->toUInteger(); |
|---|
| 1637 |
else |
|---|
| 1638 |
insnTemplate << "$" << e->toInteger(); |
|---|
| 1639 |
break; |
|---|
| 1640 |
|
|---|
| 1641 |
case Arg_Pointer: |
|---|
| 1642 |
stmt->error ( "unsupported pointer reference to '%s' in naked asm", e->toChars() ); |
|---|
| 1643 |
break; |
|---|
| 1644 |
|
|---|
| 1645 |
case Arg_Memory: |
|---|
| 1646 |
if ( e->op == TOKvar ) |
|---|
| 1647 |
{ |
|---|
| 1648 |
VarExp* v = ( VarExp* ) e; |
|---|
| 1649 |
if ( VarDeclaration* vd = v->var->isVarDeclaration() ) |
|---|
| 1650 |
{ |
|---|
| 1651 |
if ( !vd->isDataseg() ) |
|---|
| 1652 |
{ |
|---|
| 1653 |
stmt->error ( "only global variables can be referenced by identifier in naked asm" ); |
|---|
| 1654 |
break; |
|---|
| 1655 |
} |
|---|
| 1656 |
|
|---|
| 1657 |
// osx needs an extra underscore |
|---|
| 1658 |
if ( global.params.os == OSMacOSX || global.params.os == OSWindows ) |
|---|
| 1659 |
insnTemplate << "_"; |
|---|
| 1660 |
|
|---|
| 1661 |
// print out the mangle |
|---|
| 1662 |
insnTemplate << vd->mangle(); |
|---|
| 1663 |
vd->nakedUse = true; |
|---|
| 1664 |
break; |
|---|
| 1665 |
} |
|---|
| 1666 |
} |
|---|
| 1667 |
stmt->error ( "unsupported memory reference to '%s' in naked asm", e->toChars() ); |
|---|
| 1668 |
break; |
|---|
| 1669 |
|
|---|
| 1670 |
default: |
|---|
| 1671 |
assert ( 0 && "asm unsupported arg" ); |
|---|
| 1672 |
break; |
|---|
| 1673 |
} |
|---|
| 1674 |
} |
|---|
| 1675 |
else |
|---|
| 1676 |
{ |
|---|
| 1677 |
insnTemplate << fmt |
|---|
| 1678 |
<< "<<" << (mode==Mode_Input ? "in" : "out") << asmcode->args.size() << ">>"; |
|---|
| 1679 |
asmcode->args.push_back ( AsmArg ( type, e, mode ) ); |
|---|
| 1680 |
} |
|---|
| 1681 |
} |
|---|
| 1682 |
void addOperand2 ( const char * fmtpre, const char * fmtpost, AsmArgType type, Expression * e, AsmCode * asmcode, AsmArgMode mode = Mode_Input ) |
|---|
| 1683 |
{ |
|---|
| 1684 |
if ( sc->func->naked ) |
|---|
| 1685 |
{ |
|---|
| 1686 |
// taken from above |
|---|
| 1687 |
stmt->error ( "only global variables can be referenced by identifier in naked asm" ); |
|---|
| 1688 |
return; |
|---|
| 1689 |
} |
|---|
| 1690 |
|
|---|
| 1691 |
insnTemplate << fmtpre |
|---|
| 1692 |
<< "<<" << (mode==Mode_Input ? "in" : "out") << ">>" |
|---|
| 1693 |
<< fmtpost; |
|---|
| 1694 |
asmcode->args.push_back ( AsmArg ( type, e, mode ) ); |
|---|
| 1695 |
} |
|---|
| 1696 |
|
|---|
| 1697 |
void addLabel ( char* id ) |
|---|
| 1698 |
{ |
|---|
| 1699 |
insnTemplate << sc->func->mangle() << "_" << id; |
|---|
| 1700 |
} |
|---|
| 1701 |
|
|---|
| 1702 |
/* Determines whether the operand is a register, memory reference |
|---|
| 1703 |
or immediate. Immediate addresses are currently classified as |
|---|
| 1704 |
memory. This function is called before the exact instructions |
|---|
| 1705 |
is known and thus, should not use opInfo. */ |
|---|
| 1706 |
void classifyOperand ( Operand * operand ) |
|---|
| 1707 |
{ |
|---|
| 1708 |
operand->cls = classifyOperand1 ( operand ); |
|---|
| 1709 |
} |
|---|
| 1710 |
|
|---|
| 1711 |
OperandClass classifyOperand1 ( Operand * operand ) |
|---|
| 1712 |
{ |
|---|
| 1713 |
bool is_localsize = false; |
|---|
| 1714 |
bool really_have_symbol = false; |
|---|
| 1715 |
|
|---|
| 1716 |
if ( operand->symbolDisplacement.dim ) |
|---|
| 1717 |
{ |
|---|
| 1718 |
is_localsize = isLocalSize ( ( Expression * ) operand->symbolDisplacement.data[0] ); |
|---|
| 1719 |
really_have_symbol = ! is_localsize; |
|---|
| 1720 |
} |
|---|
| 1721 |
|
|---|
| 1722 |
if ( operand->isOffset && ! operand->hasBracket ) |
|---|
| 1723 |
return Opr_Immediate; |
|---|
| 1724 |
|
|---|
| 1725 |
if ( operand->hasBracket || really_have_symbol ) // %% redo for 'offset' function |
|---|
| 1726 |
{ |
|---|
| 1727 |
if ( operand->reg != Reg_Invalid ) |
|---|
| 1728 |
{ |
|---|
| 1729 |
invalidExpression(); |
|---|
| 1730 |
return Opr_Invalid; |
|---|
| 1731 |
} |
|---|
| 1732 |
|
|---|
| 1733 |
return Opr_Mem; |
|---|
| 1734 |
} |
|---|
| 1735 |
|
|---|
| 1736 |
if ( operand->reg != Reg_Invalid && operand->constDisplacement != 0 ) |
|---|
| 1737 |
{ |
|---|
| 1738 |
invalidExpression(); |
|---|
| 1739 |
return Opr_Invalid; |
|---|
| 1740 |
} |
|---|
| 1741 |
|
|---|
| 1742 |
if ( operand->segmentPrefix != Reg_Invalid ) |
|---|
| 1743 |
{ |
|---|
| 1744 |
if ( operand->reg != Reg_Invalid ) |
|---|
| 1745 |
{ |
|---|
| 1746 |
invalidExpression(); |
|---|
| 1747 |
return Opr_Invalid; |
|---|
| 1748 |
} |
|---|
| 1749 |
|
|---|
| 1750 |
return Opr_Mem; |
|---|
| 1751 |
} |
|---|
| 1752 |
|
|---|
| 1753 |
if ( operand->reg != Reg_Invalid && ! operand->hasNumber ) |
|---|
| 1754 |
return Opr_Reg; |
|---|
| 1755 |
|
|---|
| 1756 |
// should check immediate given (operand->hasNumber); |
|---|
| 1757 |
// |
|---|
| 1758 |
if ( operand->hasNumber || is_localsize ) |
|---|
| 1759 |
{ |
|---|
| 1760 |
// size determination not correct if there are symbols Opr_Immediate |
|---|
| 1761 |
if ( operand->dataSize == Default_Ptr ) |
|---|
| 1762 |
{ |
|---|
| 1763 |
if ( operand->constDisplacement < 0x100 ) |
|---|
| 1764 |
operand->dataSize = Byte_Ptr; |
|---|
| 1765 |
else if ( operand->constDisplacement < 0x10000 ) |
|---|
| 1766 |
operand->dataSize = Short_Ptr; |
|---|
| 1767 |
else if ( operand->constDisplacement <= 0xFFFFFFFF ) |
|---|
| 1768 |
operand->dataSize = Int_Ptr; |
|---|
| 1769 |
else |
|---|
| 1770 |
//This could be possible since we are using 48 bits |
|---|
| 1771 |
operand->dataSize = QWord_Ptr; |
|---|
| 1772 |
} |
|---|
| 1773 |
return Opr_Immediate; |
|---|
| 1774 |
} |
|---|
| 1775 |
|
|---|
| 1776 |
// probably a bug,? |
|---|
| 1777 |
stmt->error ( "invalid operand" ); |
|---|
| 1778 |
return Opr_Invalid; |
|---|
| 1779 |
} |
|---|
| 1780 |
|
|---|
| 1781 |
void writeReg ( Reg reg ) |
|---|
| 1782 |
{ |
|---|
| 1783 |
insnTemplate << "%" << regInfo[reg].gccName; |
|---|
| 1784 |
} |
|---|
| 1785 |
|
|---|
| 1786 |
bool opTakesLabel() |
|---|
| 1787 |
{ |
|---|
| 1788 |
switch ( op ) |
|---|
| 1789 |
{ |
|---|
| 1790 |
case Op_Branch: |
|---|
| 1791 |
case Op_CBranch: |
|---|
| 1792 |
case Op_Loop: |
|---|
| 1793 |
return true; |
|---|
| 1794 |
default: |
|---|
| 1795 |
return false; |
|---|
| 1796 |
} |
|---|
| 1797 |
} |
|---|
| 1798 |
|
|---|
| 1799 |
bool getTypeChar ( TypeNeeded needed, PtrType ptrtype, char & type_char ) |
|---|
| 1800 |
{ |
|---|
| 1801 |
switch ( needed ) |
|---|
| 1802 |
{ |
|---|
| 1803 |
case Byte_NoType: |
|---|
| 1804 |
return ptrtype == Byte_Ptr; |
|---|
| 1805 |
case Word_Types: |
|---|
| 1806 |
if ( ptrtype == Byte_Ptr ) |
|---|
| 1807 |
return false; |
|---|
| 1808 |
// drop through |
|---|
| 1809 |
case Int_Types: |
|---|
| 1810 |
switch ( ptrtype ) |
|---|
| 1811 |
{ |
|---|
| 1812 |
case Byte_Ptr: type_char = 'b'; break; |
|---|
| 1813 |
case Short_Ptr: type_char = 'w'; break; |
|---|
| 1814 |
case Int_Ptr: type_char = 'l'; break; |
|---|
| 1815 |
case QWord_Ptr: type_char = 'q'; break; |
|---|
| 1816 |
default: |
|---|
| 1817 |
// %% these may be too strict |
|---|
| 1818 |
return false; |
|---|
| 1819 |
} |
|---|
| 1820 |
break; |
|---|
| 1821 |
case FPInt_Types: |
|---|
| 1822 |
switch ( ptrtype ) |
|---|
| 1823 |
{ |
|---|
| 1824 |
case Short_Ptr: type_char = 0; break; |
|---|
| 1825 |
case Int_Ptr: type_char = 'l'; break; |
|---|
| 1826 |
case QWord_Ptr: type_char = 'q'; break; |
|---|
| 1827 |
default: |
|---|
| 1828 |
return false; |
|---|
| 1829 |
} |
|---|
| 1830 |
break; |
|---|
| 1831 |
case FP_Types: |
|---|
| 1832 |
switch ( ptrtype ) |
|---|
| 1833 |
{ |
|---|
| 1834 |
case Float_Ptr: type_char = 's'; break; |
|---|
| 1835 |
case Double_Ptr: type_char = 'l'; break; |
|---|
| 1836 |
case Extended_Ptr: type_char = 't'; break; |
|---|
| 1837 |
default: |
|---|
| 1838 |
return false; |
|---|
| 1839 |
} |
|---|
| 1840 |
break; |
|---|
| 1841 |
default: |
|---|
| 1842 |
return false; |
|---|
| 1843 |
} |
|---|
| 1844 |
return true; |
|---|
| 1845 |
} |
|---|
| 1846 |
|
|---|
| 1847 |
// also set impl clobbers |
|---|
| 1848 |
bool formatInstruction ( int nOperands, AsmCode * asmcode ) |
|---|
| 1849 |
{ |
|---|
| 1850 |
const char *fmt; |
|---|
| 1851 |
const char *mnemonic; |
|---|
| 1852 |
char type_char = 0; |
|---|
| 1853 |
bool use_star; |
|---|
| 1854 |
AsmArgMode mode; |
|---|
| 1855 |
|
|---|
| 1856 |
insnTemplate.str(""); |
|---|
| 1857 |
// %% todo: special case for something.. |
|---|
| 1858 |
if ( opInfo->linkType == Out_Mnemonic ) |
|---|
| 1859 |
mnemonic = alternateMnemonics[opInfo->link]; |
|---|
| 1860 |
else |
|---|
| 1861 |
mnemonic = opIdent->string; |
|---|
| 1862 |
|
|---|
| 1863 |
// handle two-operand form where second arg is ignored. |
|---|
| 1864 |
// must be done before type_char detection |
|---|
| 1865 |
if ( op == Op_FidR_P || op == Op_fxch || op == Op_FfdRR_P ) |
|---|
| 1866 |
{ |
|---|
| 1867 |
if (operands[1].cls == Opr_Reg && operands[1].reg == Reg_ST ) |
|---|
| 1868 |
nOperands = 1; |
|---|
| 1869 |
else |
|---|
| 1870 |
stmt->error("instruction allows only ST as second argument"); |
|---|
| 1871 |
} |
|---|
| 1872 |
|
|---|
| 1873 |
if ( opInfo->needsType ) |
|---|
| 1874 |
{ |
|---|
| 1875 |
PtrType exact_type = Default_Ptr; |
|---|
| 1876 |
PtrType min_type = Default_Ptr; |
|---|
| 1877 |
PtrType hint_type = Default_Ptr; |
|---|
| 1878 |
|
|---|
| 1879 |
/* Default types: This attempts to match the observed behavior of DMD */ |
|---|
| 1880 |
switch ( opInfo->needsType ) |
|---|
| 1881 |
{ |
|---|
| 1882 |
case Int_Types: min_type = Byte_Ptr; break; |
|---|
| 1883 |
case Word_Types: min_type = Short_Ptr; break; |
|---|
| 1884 |
case FPInt_Types: |
|---|
| 1885 |
if ( op == Op_Fis_ST ) // integer math instructions |
|---|
| 1886 |
min_type = Int_Ptr; |
|---|
| 1887 |
else // compare, load, store |
|---|
| 1888 |
min_type = Short_Ptr; |
|---|
| 1889 |
break; |
|---|
| 1890 |
case FP_Types: min_type = Float_Ptr; break; |
|---|
| 1891 |
} |
|---|
| 1892 |
if ( op == Op_push && operands[0].cls == Opr_Immediate ) |
|---|
| 1893 |
min_type = QWord_Ptr; |
|---|
| 1894 |
|
|---|
| 1895 |
for ( int i = 0; i < nOperands; i++ ) |
|---|
| 1896 |
{ |
|---|
| 1897 |
if ( hint_type == Default_Ptr && |
|---|
| 1898 |
! ( opInfo->operands[i] & Opr_NoType ) ) |
|---|
| 1899 |
hint_type = operands[i].dataSizeHint; |
|---|
| 1900 |
|
|---|
| 1901 |
if ( ( opInfo->operands[i] & Opr_NoType ) || |
|---|
| 1902 |
operands[i].dataSize == Default_Ptr ) |
|---|
| 1903 |
continue; |
|---|
| 1904 |
if ( operands[i].cls == Opr_Immediate ) |
|---|
| 1905 |
{ |
|---|
| 1906 |
min_type = operands[i].dataSize > min_type ? |
|---|
| 1907 |
operands[i].dataSize : min_type; |
|---|
| 1908 |
} |
|---|
| 1909 |
else |
|---|
| 1910 |
{ |
|---|
| 1911 |
exact_type = operands[i].dataSize; // could check for conflicting types |
|---|
| 1912 |
break; |
|---|
| 1913 |
} |
|---|
| 1914 |
} |
|---|
| 1915 |
|
|---|
| 1916 |
bool type_ok; |
|---|
| 1917 |
if ( exact_type == Default_Ptr ) |
|---|
| 1918 |
{ |
|---|
| 1919 |
type_ok = getTypeChar ( ( TypeNeeded ) opInfo->needsType, hint_type, type_char ); |
|---|
| 1920 |
if ( ! type_ok ) |
|---|
| 1921 |
type_ok = getTypeChar ( ( TypeNeeded ) opInfo->needsType, min_type, type_char ); |
|---|
| 1922 |
} |
|---|
| 1923 |
else |
|---|
| 1924 |
type_ok = getTypeChar ( ( TypeNeeded ) opInfo->needsType, exact_type, type_char ); |
|---|
| 1925 |
|
|---|
| 1926 |
if ( ! type_ok ) |
|---|
| 1927 |
{ |
|---|
| 1928 |
stmt->error ( "invalid operand size" ); |
|---|
| 1929 |
return false; |
|---|
| 1930 |
} |
|---|
| 1931 |
} |
|---|
| 1932 |
else if ( op == Op_Branch ) |
|---|
| 1933 |
{ |
|---|
| 1934 |
if ( operands[0].dataSize == Far_Ptr ) // %% type=Far_Ptr not set by Seg:Ofss OTOH, we don't support that.. |
|---|
| 1935 |
insnTemplate << 'l'; |
|---|
| 1936 |
} |
|---|
| 1937 |
else if ( op == Op_FMath0 || op == Op_FdST0ST1 ) |
|---|
| 1938 |
{ |
|---|
| 1939 |
operands[0].cls = Opr_Reg; |
|---|
| 1940 |
operands[0].reg = Reg_ST1; |
|---|
| 1941 |
operands[1].cls = Opr_Reg; |
|---|
| 1942 |
operands[1].reg = Reg_ST; |
|---|
| 1943 |
nOperands = 2; |
|---|
| 1944 |
} |
|---|
| 1945 |
|
|---|
| 1946 |
switch ( op ) |
|---|
| 1947 |
{ |
|---|
| 1948 |
case Op_SizedStack: |
|---|
| 1949 |
{ |
|---|
| 1950 |
int mlen = strlen ( mnemonic ); |
|---|
| 1951 |
if ( mnemonic[mlen-1] == 'd' ) |
|---|
| 1952 |
insnTemplate.write(mnemonic, mlen-1); |
|---|
| 1953 |
else |
|---|
| 1954 |
{ |
|---|
| 1955 |
insnTemplate << mnemonic << 'w'; |
|---|
| 1956 |
} |
|---|
| 1957 |
} |
|---|
| 1958 |
break; |
|---|
| 1959 |
case Op_cmpsd: |
|---|
| 1960 |
case Op_insX: |
|---|
| 1961 |
case Op_lodsX: |
|---|
| 1962 |
case Op_movsd: |
|---|
| 1963 |
case Op_outsX: |
|---|
| 1964 |
case Op_scasX: |
|---|
| 1965 |
case Op_stosX: |
|---|
| 1966 |
{ |
|---|
| 1967 |
int mlen = strlen ( mnemonic ); |
|---|
| 1968 |
if ( mnemonic[mlen-1] == 'd' ) |
|---|
| 1969 |
{ |
|---|
| 1970 |
insnTemplate.write(mnemonic, mlen-1) << 'l'; |
|---|
| 1971 |
} |
|---|
| 1972 |
else |
|---|
| 1973 |
{ |
|---|
| 1974 |
insnTemplate << mnemonic; |
|---|
| 1975 |
} |
|---|
| 1976 |
} |
|---|
| 1977 |
break; |
|---|
| 1978 |
case Op_movsx: |
|---|
| 1979 |
case Op_movzx: |
|---|
| 1980 |
{ |
|---|
| 1981 |
char tc_1; |
|---|
| 1982 |
int mlen = strlen ( mnemonic ); |
|---|
| 1983 |
PtrType op1_size = operands[1].dataSize; |
|---|
| 1984 |
if ( op1_size == Default_Ptr ) |
|---|
| 1985 |
op1_size = operands[1].dataSizeHint; |
|---|
| 1986 |
// Need type char for source arg |
|---|
| 1987 |
switch ( op1_size ) |
|---|
| 1988 |
{ |
|---|
| 1989 |
case Byte_Ptr: |
|---|
| 1990 |
case Default_Ptr: |
|---|
| 1991 |
tc_1 = 'b'; |
|---|
| 1992 |
break; |
|---|
| 1993 |
case Short_Ptr: |
|---|
| 1994 |
tc_1 = 'w'; |
|---|
| 1995 |
break; |
|---|
| 1996 |
default: |
|---|
| 1997 |
stmt->error ( "invalid operand size/type" ); |
|---|
| 1998 |
return false; |
|---|
| 1999 |
} |
|---|
| 2000 |
assert ( type_char != 0 ); |
|---|
| 2001 |
insnTemplate.write(mnemonic, mlen-1) << tc_1 << type_char; |
|---|
| 2002 |
} |
|---|
| 2003 |
break; |
|---|
| 2004 |
|
|---|
| 2005 |
default: |
|---|
| 2006 |
// special case fdiv, fsub: see dmd 840, ldc 256 |
|---|
| 2007 |
if ((strncmp(mnemonic, "fsub", 4) == 0 || |
|---|
| 2008 |
strncmp(mnemonic, "fdiv", 4) == 0) && |
|---|
| 2009 |
operands[0].reg != Reg_ST && op != Op_FMath) |
|---|
| 2010 |
{ |
|---|
| 2011 |
// replace: |
|---|
| 2012 |
// f{sub,div}r{p,} <-> f{sub,div}{p,} |
|---|
| 2013 |
if (mnemonic[4] == 'r') |
|---|
| 2014 |
{ |
|---|
| 2015 |
insnTemplate.write(mnemonic, 4); |
|---|
| 2016 |
insnTemplate.write(mnemonic+5, strlen(mnemonic)-5); |
|---|
| 2017 |
} |
|---|
| 2018 |
else |
|---|
| 2019 |
{ |
|---|
| 2020 |
insnTemplate.write(mnemonic, 4) << "r"; |
|---|
| 2021 |
insnTemplate.write(mnemonic+4, strlen(mnemonic)-4); |
|---|
| 2022 |
} |
|---|
| 2023 |
} |
|---|
| 2024 |
else |
|---|
| 2025 |
{ |
|---|
| 2026 |
insnTemplate << mnemonic; |
|---|
| 2027 |
} |
|---|
| 2028 |
// the no-operand versions of floating point ops always pop |
|---|
| 2029 |
if (op == Op_FMath0) |
|---|
| 2030 |
insnTemplate << "p"; |
|---|
| 2031 |
if ( type_char ) |
|---|
| 2032 |
insnTemplate << type_char; |
|---|
| 2033 |
break; |
|---|
| 2034 |
} |
|---|
| 2035 |
|
|---|
| 2036 |
switch ( opInfo->implicitClobbers & Clb_DXAX_Mask ) |
|---|
| 2037 |
{ |
|---|
| 2038 |
case Clb_SizeAX: |
|---|
| 2039 |
case Clb_EAX: |
|---|
| 2040 |
asmcode->regs[Reg_EAX] = true; |
|---|
| 2041 |
break; |
|---|
| 2042 |
case Clb_SizeDXAX: |
|---|
| 2043 |
asmcode->regs[Reg_EAX] = true; |
|---|
| 2044 |
if ( type_char != 'b' ) |
|---|
| 2045 |
asmcode->regs[Reg_EDX] = true; |
|---|
| 2046 |
break; |
|---|
| 2047 |
default: |
|---|
| 2048 |
// nothing |
|---|
| 2049 |
break; |
|---|
| 2050 |
} |
|---|
| 2051 |
|
|---|
| 2052 |
if ( opInfo->implicitClobbers & Clb_DI ) |
|---|
| 2053 |
asmcode->regs[Reg_EDI] = true; |
|---|
| 2054 |
if ( opInfo->implicitClobbers & Clb_SI ) |
|---|
| 2055 |
asmcode->regs[Reg_ESI] = true; |
|---|
| 2056 |
if ( opInfo->implicitClobbers & Clb_CX ) |
|---|
| 2057 |
asmcode->regs[Reg_ECX] = true; |
|---|
| 2058 |
if ( opInfo->implicitClobbers & Clb_SP ) |
|---|
| 2059 |
asmcode->regs[Reg_ESP] = true; |
|---|
| 2060 |
if ( opInfo->implicitClobbers & Clb_ST ) |
|---|
| 2061 |
{ |
|---|
| 2062 |
/* Can't figure out how to tell GCC that an |
|---|
| 2063 |
asm statement leaves an arg pushed on the stack. |
|---|
| 2064 |
Maybe if the statment had and input or output |
|---|
| 2065 |
operand it would work... In any case, clobbering |
|---|
| 2066 |
all FP prevents incorrect code generation. */ |
|---|
| 2067 |
asmcode->regs[Reg_ST] = true; |
|---|
| 2068 |
asmcode->regs[Reg_ST1] = true; |
|---|
| 2069 |
asmcode->regs[Reg_ST2] = true; |
|---|
| 2070 |
asmcode->regs[Reg_ST3] = true; |
|---|
| 2071 |
asmcode->regs[Reg_ST4] = true; |
|---|
| 2072 |
asmcode->regs[Reg_ST5] = true; |
|---|
| 2073 |
asmcode->regs[Reg_ST6] = true; |
|---|
| 2074 |
asmcode->regs[Reg_ST7] = true; |
|---|
| 2075 |
} |
|---|
| 2076 |
if ( opInfo->implicitClobbers & Clb_Flags ) |
|---|
| 2077 |
asmcode->regs[Reg_EFLAGS] = true; |
|---|
| 2078 |
if ( op == Op_cpuid ) |
|---|
| 2079 |
{ |
|---|
| 2080 |
asmcode->regs[Reg_EAX] = true; |
|---|
| 2081 |
asmcode->regs[Reg_EBX] = true; |
|---|
| 2082 |
asmcode->regs[Reg_ECX] = true; |
|---|
| 2083 |
asmcode->regs[Reg_EDX] = true; |
|---|
| 2084 |
} |
|---|
| 2085 |
|
|---|
| 2086 |
insnTemplate << ' '; |
|---|
| 2087 |
for ( int i__ = 0; i__ < nOperands; i__++ ) |
|---|
| 2088 |
{ |
|---|
| 2089 |
int i; |
|---|
| 2090 |
if ( i__ != 0 ) |
|---|
| 2091 |
insnTemplate << ", "; |
|---|
| 2092 |
|
|---|
| 2093 |
fmt = "$"; |
|---|
| 2094 |
|
|---|
| 2095 |
switch ( op ) |
|---|
| 2096 |
{ |
|---|
| 2097 |
case Op_mul: |
|---|
| 2098 |
// gas won't accept the two-operand form; skip to the source operand |
|---|
| 2099 |
i__ = 1; |
|---|
| 2100 |
// drop through |
|---|
| 2101 |
case Op_bound: |
|---|
| 2102 |
case Op_enter: |
|---|
| 2103 |
i = i__; |
|---|
| 2104 |
break; |
|---|
| 2105 |
default: |
|---|
| 2106 |
i = nOperands - 1 - i__; // operand = & operands[ nOperands - 1 - i ]; |
|---|
| 2107 |
break; |
|---|
| 2108 |
} |
|---|
| 2109 |
operand = & operands[ i ]; |
|---|
| 2110 |
|
|---|
| 2111 |
switch ( operand->cls ) |
|---|
| 2112 |
{ |
|---|
| 2113 |
case Opr_Immediate: |
|---|
| 2114 |
// for implementing offset: |
|---|
| 2115 |
// $var + $7 // fails |
|---|
| 2116 |
// $var + 7 // ok |
|---|
| 2117 |
// $7 + $var // ok |
|---|
| 2118 |
|
|---|
| 2119 |
// DMD doesn't seem to allow this |
|---|
| 2120 |
/* |
|---|
| 2121 |
if (opInfo->takesLabel()) tho... (near ptr <Number> would be abs?) |
|---|
| 2122 |
fmt = "$a"; // GAS won't accept "jmp $42"; must be "jmp 42" (rel) or "jmp *42" (abs) |
|---|
| 2123 |
*/ |
|---|
| 2124 |
if ( opTakesLabel() /*opInfo->takesLabel()*/ ) |
|---|
| 2125 |
{ |
|---|
| 2126 |
// "relative addressing not allowed in branch instructions" .. |
|---|
| 2127 |
stmt->error ( "integer constant not allowed in branch instructions" ); |
|---|
| 2128 |
return false; |
|---|
| 2129 |
} |
|---|
| 2130 |
|
|---|
| 2131 |
if ( operand->symbolDisplacement.dim && |
|---|
| 2132 |
isLocalSize ( ( Expression * ) operand->symbolDisplacement.data[0] ) ) |
|---|
| 2133 |
{ |
|---|
| 2134 |
// handle __LOCAL_SIZE, which in this constant, is an immediate |
|---|
| 2135 |
// should do this in slotexp.. |
|---|
| 2136 |
addOperand ( "$", Arg_LocalSize, |
|---|
| 2137 |
( Expression * ) operand->symbolDisplacement.data[0], asmcode ); |
|---|
| 2138 |
if ( operand->constDisplacement ) |
|---|
| 2139 |
insnTemplate << '+'; |
|---|
| 2140 |
else |
|---|
| 2141 |
break; |
|---|
| 2142 |
} |
|---|
| 2143 |
|
|---|
| 2144 |
if ( operand->symbolDisplacement.dim ) |
|---|
| 2145 |
{ |
|---|
| 2146 |
fmt = "$a"; |
|---|
| 2147 |
addOperand ( "$", Arg_Pointer, |
|---|
| 2148 |
( Expression * ) operand->symbolDisplacement.data[0], |
|---|
| 2149 |
asmcode ); |
|---|
| 2150 |
|
|---|
| 2151 |
if ( operand->constDisplacement ) |
|---|
| 2152 |
insnTemplate << '+'; |
|---|
| 2153 |
else |
|---|
| 2154 |
// skip the addOperand(fmt, Arg_Integer...) below |
|---|
| 2155 |
break; |
|---|
| 2156 |
} |
|---|
| 2157 |
addOperand ( fmt, Arg_Integer, newIntExp ( operand->constDisplacement ), asmcode ); |
|---|
| 2158 |
break; |
|---|
| 2159 |
case Opr_Reg: |
|---|
| 2160 |
if ( opInfo->operands[i] & Opr_Dest ) |
|---|
| 2161 |
{ |
|---|
| 2162 |
Reg clbr_reg = ( Reg ) regInfo[operand->reg].baseReg; |
|---|
| 2163 |
if ( clbr_reg != Reg_Invalid ) |
|---|
| 2164 |
{ |
|---|
| 2165 |
asmcode->regs[clbr_reg] = true; |
|---|
| 2166 |
} |
|---|
| 2167 |
} |
|---|
| 2168 |
if ( opTakesLabel() /*opInfo->takesLabel()*/ ) |
|---|
| 2169 |
insnTemplate << '*'; |
|---|
| 2170 |
writeReg ( operand->reg ); |
|---|
| 2171 |
/* |
|---|
| 2172 |
insnTemplate << "%"; |
|---|
| 2173 |
insnTemplate << regInfo[operand->reg].name; |
|---|
| 2174 |
*/ |
|---|
| 2175 |
break; |
|---|
| 2176 |
case Opr_Mem: |
|---|
| 2177 |
// better: use output operands for simple variable references |
|---|
| 2178 |
if ( ( opInfo->operands[i] & Opr_Update ) == Opr_Update ) |
|---|
| 2179 |
{ |
|---|
| 2180 |
mode = Mode_Update; |
|---|
| 2181 |
} |
|---|
| 2182 |
else if ( opInfo->operands[i] & Opr_Dest ) |
|---|
| 2183 |
{ |
|---|
| 2184 |
mode = Mode_Output; |
|---|
| 2185 |
} |
|---|
| 2186 |
else |
|---|
| 2187 |
{ |
|---|
| 2188 |
mode = Mode_Input; |
|---|
| 2189 |
} |
|---|
| 2190 |
|
|---|
| 2191 |
use_star = opTakesLabel();//opInfo->takesLabel(); |
|---|
| 2192 |
|
|---|
| 2193 |
if (Logger::enabled()) { |
|---|
| 2194 |
Logger::cout() << "Opr_Mem\n"; |
|---|
| 2195 |
LOG_SCOPE |
|---|
| 2196 |
Logger::cout() << "baseReg: " << operand->baseReg << '\n'; |
|---|
| 2197 |
Logger::cout() << "segmentPrefix: " << operand->segmentPrefix << '\n'; |
|---|
| 2198 |
Logger::cout() << "constDisplacement: " << operand->constDisplacement << '\n'; |
|---|
| 2199 |
for (int i = 0; i < operand->symbolDisplacement.dim; i++) { |
|---|
| 2200 |
Expression* expr = (Expression*) operand->symbolDisplacement.data[i]; |
|---|
| 2201 |
Logger::cout() << "symbolDisplacement[" << i << "] = " << expr->toChars() << '\n'; |
|---|
| 2202 |
} |
|---|
| 2203 |
} |
|---|
| 2204 |
if ( operand->segmentPrefix != Reg_Invalid ) |
|---|
| 2205 |
{ |
|---|
| 2206 |
writeReg ( operand->segmentPrefix ); |
|---|
| 2207 |
insnTemplate << ':'; |
|---|
| 2208 |
} |
|---|
| 2209 |
if ( (operand->segmentPrefix != Reg_Invalid && operand->symbolDisplacement.dim == 0) |
|---|
| 2210 |
|| operand->constDisplacement ) |
|---|
| 2211 |
{ |
|---|
| 2212 |
insnTemplate << operand->constDisplacement; |
|---|
| 2213 |
if ( operand->symbolDisplacement.dim ) |
|---|
| 2214 |
{ |
|---|
| 2215 |
insnTemplate << '+'; |
|---|
| 2216 |
} |
|---|
| 2217 |
operand->constDisplacement = 0; |
|---|
| 2218 |
//addOperand(fmt, Arg_Integer, newIntExp(operand->constDisplacement), asmcode); |
|---|
| 2219 |
if ( opInfo->operands[i] & Opr_Dest ) |
|---|
| 2220 |
asmcode->clobbersMemory = 1; |
|---|
| 2221 |
} |
|---|
| 2222 |
if ( operand->symbolDisplacement.dim ) |
|---|
| 2223 |
{ |
|---|
| 2224 |
Expression * e = ( Expression * ) operand->symbolDisplacement.data[0]; |
|---|
| 2225 |
Declaration * decl = 0; |
|---|
| 2226 |
|
|---|
| 2227 |
if ( e->op == TOKvar ) |
|---|
| 2228 |
decl = ( ( VarExp * ) e )->var; |
|---|
| 2229 |
|
|---|
| 2230 |
if ( operand->baseReg != Reg_Invalid && |
|---|
| 2231 |
decl && ! decl->isDataseg() ) |
|---|
| 2232 |
{ |
|---|
| 2233 |
|
|---|
| 2234 |
// Use the offset from frame pointer |
|---|
| 2235 |
|
|---|
| 2236 |
/* GCC doesn't give the front end access to stack offsets |
|---|
| 2237 |
when optimization is turned on (3.x) or at all (4.x). |
|---|
| 2238 |
|
|---|
| 2239 |
Try to convert var[EBP] (or var[ESP] for naked funcs) to |
|---|
| 2240 |
a memory expression that does not require us to know |
|---|
| 2241 |
the stack offset. |
|---|
| 2242 |
*/ |
|---|
| 2243 |
|
|---|
| 2244 |
if ( operand->indexReg == Reg_Invalid && |
|---|
| 2245 |
decl->isVarDeclaration() && |
|---|
| 2246 |
( ( ( operand->baseReg == Reg_EBP || ( operand->baseReg == Reg_RBP ) ) && ! sc->func->naked ) || |
|---|
| 2247 |
( ( operand->baseReg == Reg_ESP || ( operand->baseReg == Reg_RSP ) ) && ! sc->func->naked ) ) ) |
|---|
| 2248 |
{ |
|---|
| 2249 |
|
|---|
| 2250 |
e = new AddrExp ( 0, e ); |
|---|
| 2251 |
e->type = decl->type->pointerTo(); |
|---|
| 2252 |
|
|---|
| 2253 |
#if !IN_LLVM |
|---|
| 2254 |
/* DMD uses the same frame offsets for naked functions. */ |
|---|
| 2255 |
if ( sc->func->naked ) |
|---|
| 2256 |
operand->constDisplacement += 4; |
|---|
| 2257 |
|
|---|
| 2258 |
if ( operand->constDisplacement ) |
|---|
| 2259 |
{ |
|---|
| 2260 |
e = new AddExp ( 0, e, |
|---|
| 2261 |
new IntegerExp ( 0, operand->constDisplacement, |
|---|
| 2262 |
Type::tint64 ) ); |
|---|
| 2263 |
e->type = decl->type->pointerTo(); |
|---|
| 2264 |
} |
|---|
| 2265 |
e = new PtrExp ( 0, e ); |
|---|
| 2266 |
e->type = decl->type; |
|---|
| 2267 |
#endif |
|---|
| 2268 |
operand->constDisplacement = 0; |
|---|
| 2269 |
operand->baseReg = Reg_Invalid; |
|---|
| 2270 |
|
|---|
| 2271 |
addOperand ( fmt, Arg_Memory, e, asmcode, mode ); |
|---|
| 2272 |
|
|---|
| 2273 |
} |
|---|
| 2274 |
else |
|---|
| 2275 |
{ |
|---|
| 2276 |
// FIXME: what is this ? |
|---|
| 2277 |
addOperand2 ( "${",":a}", Arg_FrameRelative, e, asmcode ); |
|---|
| 2278 |
} |
|---|
| 2279 |
if ( opInfo->operands[i] & Opr_Dest ) |
|---|
| 2280 |
asmcode->clobbersMemory = 1; |
|---|
| 2281 |
} |
|---|
| 2282 |
else |
|---|
| 2283 |
{ |
|---|
| 2284 |
// Plain memory reference to variable |
|---|
| 2285 |
|
|---|
| 2286 |
/* If in a reg, DMD moves to memory.. even with -O, so we'll do the same |
|---|
| 2287 |
by always using the "m" contraint. |
|---|
| 2288 |
|
|---|
| 2289 |
In order to get the correct output for function and label symbols, |
|---|
| 2290 |
the %an format must be used with the "p" constraint. |
|---|
| 2291 |
*/ |
|---|
| 2292 |
if ( isDollar ( e ) ) |
|---|
| 2293 |
{ |
|---|
| 2294 |
error ( "dollar labels are not supported", stmt->loc.toChars() ); |
|---|
| 2295 |
asmcode->dollarLabel = 1; |
|---|
| 2296 |
} |
|---|
| 2297 |
else if ( e->op == TOKdsymbol ) |
|---|
| 2298 |
{ |
|---|
| 2299 |
LabelDsymbol * lbl = ( LabelDsymbol * ) ( ( DsymbolExp * ) e )->s; |
|---|
| 2300 |
stmt->isBranchToLabel = lbl->ident; |
|---|
| 2301 |
|
|---|
| 2302 |
use_star = false; |
|---|
| 2303 |
addLabel ( lbl->ident->toChars() ); |
|---|
| 2304 |
} |
|---|
| 2305 |
else if ( ( decl && decl->isCodeseg() ) ) // if function or label |
|---|
| 2306 |
{ |
|---|
| 2307 |
use_star = false; |
|---|
| 2308 |
// simply write out the mangle |
|---|
| 2309 |
// on osx and windows, prepend extra _ |
|---|
| 2310 |
if ( global.params.os == OSMacOSX || global.params.os == OSWindows ) |
|---|
| 2311 |
insnTemplate << "_"; |
|---|
| 2312 |
insnTemplate << decl->mangle(); |
|---|
| 2313 |
// addOperand2("${", ":c}", Arg_Pointer, e, asmcode); |
|---|
| 2314 |
} |
|---|
| 2315 |
else |
|---|
| 2316 |
{ |
|---|
| 2317 |
if ( use_star ) |
|---|
| 2318 |
{ |
|---|
| 2319 |
insnTemplate << '*'; |
|---|
| 2320 |
use_star = false; |
|---|
| 2321 |
} |
|---|
| 2322 |
|
|---|
| 2323 |
if ( !sc->func->naked ) // no addrexp in naked asm please :) |
|---|
| 2324 |
{ |
|---|
| 2325 |
Type* tt = e->type->pointerTo(); |
|---|
| 2326 |
e = new AddrExp ( 0, e ); |
|---|
| 2327 |
e->type = tt; |
|---|
| 2328 |
} |
|---|
| 2329 |
|
|---|
| 2330 |
addOperand ( fmt, Arg_Memory, e, asmcode, mode ); |
|---|
| 2331 |
} |
|---|
| 2332 |
} |
|---|
| 2333 |
} |
|---|
| 2334 |
if ( use_star ) |
|---|
| 2335 |
insnTemplate << '*'; |
|---|
| 2336 |
if ( operand->baseReg != Reg_Invalid || operand->indexReg != Reg_Invalid ) |
|---|
| 2337 |
{ |
|---|
| 2338 |
insnTemplate << '('; |
|---|
| 2339 |
if ( operand->baseReg != Reg_Invalid ) |
|---|
| 2340 |
writeReg ( operand->baseReg ); |
|---|
| 2341 |
if ( operand->indexReg != Reg_Invalid ) |
|---|
| 2342 |
{ |
|---|
| 2343 |
insnTemplate << ','; |
|---|
| 2344 |
writeReg ( operand->indexReg ); |
|---|
| 2345 |
if ( operand->scale ) |
|---|
| 2346 |
{ |
|---|
| 2347 |
insnTemplate << "," << operand->scale; |
|---|
| 2348 |
} |
|---|
| 2349 |
} |
|---|
| 2350 |
insnTemplate << ')'; |
|---|
| 2351 |
if ( opInfo->operands[i] & Opr_Dest ) |
|---|
| 2352 |
asmcode->clobbersMemory = 1; |
|---|
| 2353 |
} |
|---|
| 2354 |
break; |
|---|
| 2355 |
case Opr_Invalid: |
|---|
| 2356 |
return false; |
|---|
| 2357 |
} |
|---|
| 2358 |
} |
|---|
| 2359 |
|
|---|
| 2360 |
asmcode->insnTemplate = insnTemplate.str(); |
|---|
| 2361 |
Logger::cout() << "insnTemplate = " << asmcode->insnTemplate << '\n'; |
|---|
| 2362 |
return true; |
|---|
| 2363 |
} |
|---|
| 2364 |
|
|---|
| 2365 |
bool isIntExp ( Expression * exp ) |
|---|
| 2366 |
{ |
|---|
| 2367 |
if ( exp->op == TOKint64 ) |
|---|
| 2368 |
return 1; |
|---|
| 2369 |
if ( exp->op == TOKvar ) |
|---|
| 2370 |
{ |
|---|
| 2371 |
Declaration * v = ( ( VarExp * ) exp )->var; |
|---|
| 2372 |
if ( v->isConst() && v->type->isintegral() ) |
|---|
| 2373 |
return 1; |
|---|
| 2374 |
} |
|---|
| 2375 |
return 0; |
|---|
| 2376 |
} |
|---|
| 2377 |
bool isRegExp ( Expression * exp ) { return exp->op == TOKmod; } // ewww.%% |
|---|
| 2378 |
bool isLocalSize ( Expression * exp ) |
|---|
| 2379 |
{ |
|---|
| 2380 |
// cleanup: make a static var |
|---|
| 2381 |
return exp->op == TOKidentifier && ( ( IdentifierExp * ) exp )->ident == Id::__LOCAL_SIZE; |
|---|
| 2382 |
} |
|---|
| 2383 |
bool isDollar ( Expression * exp ) |
|---|
| 2384 |
{ |
|---|
| 2385 |
return exp->op == TOKidentifier && ( ( IdentifierExp * ) exp )->ident == Id::__dollar; |
|---|
| 2386 |
} |
|---|
| 2387 |
|
|---|
| 2388 |
Expression * newRegExp ( int regno ) |
|---|
| 2389 |
{ |
|---|
| 2390 |
IntegerExp * e = new IntegerExp ( regno ); |
|---|
| 2391 |
e->op = TOKmod; |
|---|
| 2392 |
return e; |
|---|
| 2393 |
} |
|---|
| 2394 |
|
|---|
| 2395 |
Expression * newIntExp ( long v /* %% type */ ) |
|---|
| 2396 |
{ |
|---|
| 2397 |
// Handle 64 bit ... incoming long may need to be 'long long' for Windows??? |
|---|
| 2398 |
return new IntegerExp ( stmt->loc, v, Type::tint64 ); |
|---|
| 2399 |
} |
|---|
| 2400 |
|
|---|
| 2401 |
void slotExp ( Expression * exp ) |
|---|
| 2402 |
{ |
|---|
| 2403 |
/* |
|---|
| 2404 |
if offset, make a note |
|---|
| 2405 |
|
|---|
| 2406 |
if integer, add to immediate |
|---|
| 2407 |
if reg: |
|---|
| 2408 |
if not in bracket, set reg (else error) |
|---|
| 2409 |
if in bracket: |
|---|
| 2410 |
if not base, set base |
|---|
| 2411 |
if not index, set index |
|---|
| 2412 |
else, error |
|---|
| 2413 |
if symbol: |
|---|
| 2414 |
set symbol field |
|---|
| 2415 |
*/ |
|---|
| 2416 |
|
|---|
| 2417 |
bool is_offset = false; |
|---|
| 2418 |
if ( exp->op == TOKaddress ) |
|---|
| 2419 |
{ |
|---|
| 2420 |
exp = ( ( AddrExp * ) exp )->e1; |
|---|
| 2421 |
is_offset = true; |
|---|
| 2422 |
} |
|---|
| 2423 |
|
|---|
| 2424 |
if ( isIntExp ( exp ) ) |
|---|
| 2425 |
{ |
|---|
| 2426 |
if ( is_offset ) |
|---|
| 2427 |
invalidExpression(); |
|---|
| 2428 |
operand->constDisplacement += exp->toInteger(); |
|---|
| 2429 |
if ( ! operand->inBracket ) |
|---|
| 2430 |
operand->hasNumber = 1; |
|---|
| 2431 |
} |
|---|
| 2432 |
else if ( isRegExp ( exp ) ) |
|---|
| 2433 |
{ |
|---|
| 2434 |
if ( is_offset ) |
|---|
| 2435 |
invalidExpression(); |
|---|
| 2436 |
if ( ! operand->inBracket ) |
|---|
| 2437 |
{ |
|---|
| 2438 |
if ( operand->reg == Reg_Invalid ) |
|---|
| 2439 |
operand->reg = ( Reg ) exp->toInteger(); |
|---|
| 2440 |
else |
|---|
| 2441 |
stmt->error ( "too many registers in operand (use brackets)" ); |
|---|
| 2442 |
} |
|---|
| 2443 |
else |
|---|
| 2444 |
{ |
|---|
| 2445 |
if ( operand->baseReg == Reg_Invalid ) |
|---|
| 2446 |
operand->baseReg = ( Reg ) exp->toInteger(); |
|---|
| 2447 |
else if ( operand->indexReg == Reg_Invalid ) |
|---|
| 2448 |
{ |
|---|
| 2449 |
operand->indexReg = ( Reg ) exp->toInteger(); |
|---|
| 2450 |
operand->scale = 1; |
|---|
| 2451 |
} |
|---|
| 2452 |
else |
|---|
| 2453 |
{ |
|---|
| 2454 |
stmt->error ( "too many registers memory operand" ); |
|---|
| 2455 |
} |
|---|
| 2456 |
} |
|---|
| 2457 |
} |
|---|
| 2458 |
else if ( exp->op == TOKvar ) |
|---|
| 2459 |
{ |
|---|
| 2460 |
VarDeclaration * v = ( ( VarExp * ) exp )->var->isVarDeclaration(); |
|---|
| 2461 |
|
|---|
| 2462 |
if ( v && v->storage_class & STCfield ) |
|---|
| 2463 |
{ |
|---|
| 2464 |
operand->constDisplacement += v->offset; |
|---|
| 2465 |
if ( ! operand->inBracket ) |
|---|
| 2466 |
operand->hasNumber = 1; |
|---|
| 2467 |
} |
|---|
| 2468 |
else |
|---|
| 2469 |
{ |
|---|
| 2470 |
if ( v && v->type->isscalar() ) |
|---|
| 2471 |
{ |
|---|
| 2472 |
// DMD doesn't check Tcomplex*, and counts Tcomplex32 as Tfloat64 |
|---|
| 2473 |
TY ty = v->type->toBasetype()->ty; |
|---|
| 2474 |
operand->dataSizeHint = ty == Tfloat80 || ty == Timaginary80 ? |
|---|
| 2475 |
Extended_Ptr : ( PtrType ) v->type->size ( 0 ); |
|---|
| 2476 |
} |
|---|
| 2477 |
|
|---|
| 2478 |
if ( ! operand->symbolDisplacement.dim ) |
|---|
| 2479 |
{ |
|---|
| 2480 |
if ( is_offset && ! operand->inBracket ) |
|---|
| 2481 |
operand->isOffset = 1; |
|---|
| 2482 |
operand->symbolDisplacement.push ( exp ); |
|---|
| 2483 |
} |
|---|
| 2484 |
else |
|---|
| 2485 |
{ |
|---|
| 2486 |
stmt->error ( "too many symbols in operand" ); |
|---|
| 2487 |
} |
|---|
| 2488 |
} |
|---|
| 2489 |
} |
|---|
| 2490 |
else if ( exp->op == TOKidentifier || exp->op == TOKdsymbol ) |
|---|
| 2491 |
{ |
|---|
| 2492 |
// %% localsize could be treated as a simple constant.. |
|---|
| 2493 |
// change to addSymbolDisp(e) |
|---|
| 2494 |
if ( ! operand->symbolDisplacement.dim ) |
|---|
| 2495 |
{ |
|---|
| 2496 |
operand->symbolDisplacement.push ( exp ); |
|---|
| 2497 |
} |
|---|
| 2498 |
else |
|---|
| 2499 |
{ |
|---|
| 2500 |
stmt->error ( "too many symbols in operand" ); |
|---|
| 2501 |
} |
|---|
| 2502 |
} |
|---|
| 2503 |
else if ( exp == Handled ) |
|---|
| 2504 |
{ |
|---|
| 2505 |
// nothing |
|---|
| 2506 |
} |
|---|
| 2507 |
else |
|---|
| 2508 |
{ |
|---|
| 2509 |
stmt->error ( "invalid operand" ); |
|---|
| 2510 |
} |
|---|
| 2511 |
} |
|---|
| 2512 |
|
|---|
| 2513 |
void invalidExpression() |
|---|
| 2514 |
{ |
|---|
| 2515 |
// %% report operand number |
|---|
| 2516 |
stmt->error ( "invalid expression" ); |
|---|
| 2517 |
} |
|---|
| 2518 |
|
|---|
| 2519 |
Expression * intOp ( TOK op, Expression * e1, Expression * e2 ) |
|---|
| 2520 |
{ |
|---|
| 2521 |
Expression * e; |
|---|
| 2522 |
if ( isIntExp ( e1 ) && ( ! e2 || isIntExp ( e2 ) ) ) |
|---|
| 2523 |
{ |
|---|
| 2524 |
switch ( op ) |
|---|
| 2525 |
{ |
|---|
| 2526 |
case TOKadd: |
|---|
| 2527 |
if ( e2 ) |
|---|
| 2528 |
e = new AddExp ( stmt->loc, e1, e2 ); |
|---|
| 2529 |
else |
|---|
| 2530 |
e = e1; |
|---|
| 2531 |
break; |
|---|
| 2532 |
case TOKmin: |
|---|
| 2533 |
if ( e2 ) |
|---|
| 2534 |
e = new MinExp ( stmt->loc, e1, e2 ); |
|---|
| 2535 |
else |
|---|
| 2536 |
e = new NegExp ( stmt->loc, e1 ); |
|---|
| 2537 |
break; |
|---|
| 2538 |
case TOKmul: |
|---|
| 2539 |
e = new MulExp ( stmt->loc, e1, e2 ); |
|---|
| 2540 |
break; |
|---|
| 2541 |
case TOKdiv: |
|---|
| 2542 |
e = new DivExp ( stmt->loc, e1, e2 ); |
|---|
| 2543 |
break; |
|---|
| 2544 |
case TOKmod: |
|---|
| 2545 |
e = new ModExp ( stmt->loc, e1, e2 ); |
|---|
| 2546 |
break; |
|---|
| 2547 |
case TOKshl: |
|---|
| 2548 |
e = new ShlExp ( stmt->loc, e1, e2 ); |
|---|
| 2549 |
break; |
|---|
| 2550 |
case TOKshr: |
|---|
| 2551 |
e = new ShrExp ( stmt->loc, e1, e2 ); |
|---|
| 2552 |
break; |
|---|
| 2553 |
case TOKushr: |
|---|
| 2554 |
e = new UshrExp ( stmt->loc, e1, e2 ); |
|---|
| 2555 |
break; |
|---|
| 2556 |
case TOKnot: |
|---|
| 2557 |
e = new NotExp ( stmt->loc, e1 ); |
|---|
| 2558 |
break; |
|---|
| 2559 |
case TOKtilde: |
|---|
| 2560 |
e = new ComExp ( stmt->loc, e1 ); |
|---|
| 2561 |
break; |
|---|
| 2562 |
default: |
|---|
| 2563 |
assert ( 0 ); |
|---|
| 2564 |
} |
|---|
| 2565 |
e = e->semantic ( sc ); |
|---|
| 2566 |
return e->optimize ( WANTvalue | WANTinterpret ); |
|---|
| 2567 |
} |
|---|
| 2568 |
else |
|---|
| 2569 |
{ |
|---|
| 2570 |
stmt->error ( "expected integer operand(s) for '%s'", Token::tochars[op] ); |
|---|
| 2571 |
return newIntExp ( 0 ); |
|---|
| 2572 |
} |
|---|
| 2573 |
} |
|---|
| 2574 |
|
|---|
| 2575 |
void parseOperand() |
|---|
| 2576 |
{ |
|---|
| 2577 |
Expression * exp = parseAsmExp(); |
|---|
| 2578 |
slotExp ( exp ); |
|---|
| 2579 |
if ( isRegExp ( exp ) ) |
|---|
| 2580 |
operand->dataSize = ( PtrType ) regInfo[exp->toInteger() ].size; |
|---|
| 2581 |
} |
|---|
| 2582 |
|
|---|
| 2583 |
Expression * parseAsmExp() |
|---|
| 2584 |
{ |
|---|
| 2585 |
return parseShiftExp(); |
|---|
| 2586 |
} |
|---|
| 2587 |
|
|---|
| 2588 |
Expression * parseShiftExp() |
|---|
| 2589 |
{ |
|---|
| 2590 |
Expression * e1 = parseAddExp(); |
|---|
| 2591 |
Expression * e2; |
|---|
| 2592 |
|
|---|
| 2593 |
while ( 1 ) |
|---|
| 2594 |
{ |
|---|
| 2595 |
TOK tv = token->value; |
|---|
| 2596 |
switch ( tv ) |
|---|
| 2597 |
{ |
|---|
| 2598 |
case TOKshl: |
|---|
| 2599 |
case TOKshr: |
|---|
| 2600 |
case TOKushr: |
|---|
| 2601 |
nextToken(); |
|---|
| 2602 |
e2 = parseAddExp(); |
|---|
| 2603 |
e1 = intOp ( tv, e1, e2 ); |
|---|
| 2604 |
continue; |
|---|
| 2605 |
default: |
|---|
| 2606 |
break; |
|---|
| 2607 |
} |
|---|
| 2608 |
break; |
|---|
| 2609 |
} |
|---|
| 2610 |
return e1; |
|---|
| 2611 |
} |
|---|
| 2612 |
|
|---|
| 2613 |
Expression * parseAddExp() |
|---|
| 2614 |
{ |
|---|
| 2615 |
Expression * e1 = parseMultExp(); |
|---|
| 2616 |
Expression * e2; |
|---|
| 2617 |
|
|---|
| 2618 |
while ( 1 ) |
|---|
| 2619 |
{ |
|---|
| 2620 |
TOK tv = token->value; |
|---|
| 2621 |
switch ( tv ) |
|---|
| 2622 |
{ |
|---|
| 2623 |
case TOKadd: |
|---|
| 2624 |
nextToken(); |
|---|
| 2625 |
e2 = parseMultExp(); |
|---|
| 2626 |
if ( isIntExp ( e1 ) && isIntExp ( e2 ) ) |
|---|
| 2627 |
e1 = intOp ( tv, e1, e2 ); |
|---|
| 2628 |
else |
|---|
| 2629 |
{ |
|---|
| 2630 |
slotExp ( e1 ); |
|---|
| 2631 |
slotExp ( e2 ); |
|---|
| 2632 |
e1 = Handled; |
|---|
| 2633 |
} |
|---|
| 2634 |
continue; |
|---|
| 2635 |
case TOKmin: |
|---|
| 2636 |
// Note: no support for symbol address difference |
|---|
| 2637 |
nextToken(); |
|---|
| 2638 |
e2 = parseMultExp(); |
|---|
| 2639 |
if ( isIntExp ( e1 ) && isIntExp ( e2 ) ) |
|---|
| 2640 |
e1 = intOp ( tv, e1, e2 ); |
|---|
| 2641 |
else |
|---|
| 2642 |
{ |
|---|
| 2643 |
slotExp ( e1 ); |
|---|
| 2644 |
e2 = intOp ( TOKmin, e2, NULL ); // verifies e2 is an int |
|---|
| 2645 |
slotExp ( e2 ); |
|---|
| 2646 |
e1 = Handled; |
|---|
| 2647 |
} |
|---|
| 2648 |
continue; |
|---|
| 2649 |
default: |
|---|
| 2650 |
break; |
|---|
| 2651 |
} |
|---|
| 2652 |
break; |
|---|
| 2653 |
} |
|---|
| 2654 |
return e1; |
|---|
| 2655 |
} |
|---|
| 2656 |
|
|---|
| 2657 |
bool tryScale ( Expression * e1, Expression * e2 ) |
|---|
| 2658 |
{ |
|---|
| 2659 |
Expression * et; |
|---|
| 2660 |
if ( isIntExp ( e1 ) && isRegExp ( e2 ) ) |
|---|
| 2661 |
{ |
|---|
| 2662 |
et = e1; |
|---|
| 2663 |
e1 = e2; |
|---|
| 2664 |
e2 = et; |
|---|
| 2665 |
goto do_scale; |
|---|
| 2666 |
} |
|---|
| 2667 |
else if ( isRegExp ( e1 ) && isIntExp ( e2 ) ) |
|---|
| 2668 |
{ |
|---|
| 2669 |
do_scale: |
|---|
| 2670 |
if ( ! operand->inBracket ) |
|---|
| 2671 |
{ |
|---|
| 2672 |
invalidExpression(); // maybe should allow, e.g. DS:EBX+EAX*4 |
|---|
| 2673 |
} |
|---|
| 2674 |
|
|---|
| 2675 |
if ( operand->scale || operand->indexReg != Reg_Invalid ) |
|---|
| 2676 |
{ |
|---|
| 2677 |
invalidExpression(); |
|---|
| 2678 |
return true; |
|---|
| 2679 |
} |
|---|
| 2680 |
|
|---|
| 2681 |
operand->indexReg = ( Reg ) e1->toInteger(); |
|---|
| 2682 |
operand->scale = e2->toInteger(); |
|---|
| 2683 |
switch ( operand->scale ) |
|---|
| 2684 |
{ |
|---|
| 2685 |
case 1: |
|---|
| 2686 |
case 2: |
|---|
| 2687 |
case 4: |
|---|
| 2688 |
case 8: |
|---|
| 2689 |
// ok; do nothing |
|---|
| 2690 |
break; |
|---|
| 2691 |
default: |
|---|
| 2692 |
stmt->error ( "invalid index register scale '%d'", operand->scale ); |
|---|
| 2693 |
return true; |
|---|
| 2694 |
} |
|---|
| 2695 |
|
|---|
| 2696 |
return true; |
|---|
| 2697 |
} |
|---|
| 2698 |
return false; |
|---|
| 2699 |
} |
|---|
| 2700 |
|
|---|
| 2701 |
Expression * parseMultExp() |
|---|
| 2702 |
{ |
|---|
| 2703 |
Expression * e1 = parseBrExp(); |
|---|
| 2704 |
Expression * e2; |
|---|
| 2705 |
|
|---|
| 2706 |
while ( 1 ) |
|---|
| 2707 |
{ |
|---|
| 2708 |
TOK tv = token->value; |
|---|
| 2709 |
switch ( tv ) |
|---|
| 2710 |
{ |
|---|
| 2711 |
case TOKmul: |
|---|
| 2712 |
nextToken(); |
|---|
| 2713 |
e2 = parseMultExp(); |
|---|
| 2714 |
if ( isIntExp ( e1 ) && isIntExp ( e2 ) ) |
|---|
| 2715 |
e1 = intOp ( tv, e1, e2 ); |
|---|
| 2716 |
else if ( tryScale ( e1,e2 ) ) |
|---|
| 2717 |
e1 = Handled; |
|---|
| 2718 |
else |
|---|
| 2719 |
invalidExpression(); |
|---|
| 2720 |
continue; |
|---|
| 2721 |
case TOKdiv: |
|---|
| 2722 |
case TOKmod: |
|---|
| 2723 |
nextToken(); |
|---|
| 2724 |
e2 = parseMultExp(); |
|---|
| 2725 |
e1 = intOp ( tv, e1, e2 ); |
|---|
| 2726 |
continue; |
|---|
| 2727 |
default: |
|---|
| 2728 |
break; |
|---|
| 2729 |
} |
|---|
| 2730 |
break; |
|---|
| 2731 |
} |
|---|
| 2732 |
return e1; |
|---|
| 2733 |
} |
|---|
| 2734 |
|
|---|
| 2735 |
Expression * parseBrExp() |
|---|
| 2736 |
{ |
|---|
| 2737 |
// %% check (why is bracket lower precends..) |
|---|
| 2738 |
// 3+4[eax] -> 3 + (4 [EAX]) .. |
|---|
| 2739 |
|
|---|
| 2740 |
// only one bracked allowed, so this doesn't quite handle |
|---|
| 2741 |
// the spec'd syntax |
|---|
| 2742 |
Expression * e; |
|---|
| 2743 |
|
|---|
| 2744 |
if ( token->value == TOKlbracket ) |
|---|
| 2745 |
e = Handled; |
|---|
| 2746 |
else |
|---|
| 2747 |
e = parseUnaExp(); |
|---|
| 2748 |
|
|---|
| 2749 |
// DMD allows multiple bracket expressions. |
|---|
| 2750 |
while ( token->value == TOKlbracket ) |
|---|
| 2751 |
{ |
|---|
| 2752 |
nextToken(); |
|---|
| 2753 |
|
|---|
| 2754 |
operand->inBracket = operand->hasBracket = 1; |
|---|
| 2755 |
slotExp ( parseAsmExp() ); |
|---|
| 2756 |
operand->inBracket = 0; |
|---|
| 2757 |
|
|---|
| 2758 |
if ( token->value == TOKrbracket ) |
|---|
| 2759 |
nextToken(); |
|---|
| 2760 |
else |
|---|
| 2761 |
stmt->error ( "missing ']'" ); |
|---|
| 2762 |
} |
|---|
| 2763 |
|
|---|
| 2764 |
return e; |
|---|
| 2765 |
} |
|---|
| 2766 |
|
|---|
| 2767 |
PtrType isPtrType ( Token * tok ) |
|---|
| 2768 |
{ |
|---|
| 2769 |
switch ( tok->value ) |
|---|
| 2770 |
{ |
|---|
| 2771 |
case TOKint8: return Byte_Ptr; |
|---|
| 2772 |
case TOKint16: return Short_Ptr; |
|---|
| 2773 |
case TOKint32: return Int_Ptr; |
|---|
| 2774 |
case TOKint64: return QWord_Ptr; |
|---|
| 2775 |
// 'long ptr' isn't accepted? (it is now for x64 - qword) |
|---|
| 2776 |
case TOKfloat32: return Float_Ptr; |
|---|
| 2777 |
case TOKfloat64: return Double_Ptr; |
|---|
| 2778 |
case TOKfloat80: return Extended_Ptr; |
|---|
| 2779 |
case TOKidentifier: |
|---|
| 2780 |
for ( int i = 0; i < N_PtrNames; i++ ) |
|---|
| 2781 |
if ( tok->ident == ptrTypeIdentTable[i] ) |
|---|
| 2782 |
return ptrTypeValueTable[i]; |
|---|
| 2783 |
break; |
|---|
| 2784 |
default: |
|---|
| 2785 |
break; |
|---|
| 2786 |
} |
|---|
| 2787 |
return Default_Ptr; |
|---|
| 2788 |
} |
|---|
| 2789 |
|
|---|
| 2790 |
Expression * parseUnaExp() |
|---|
| 2791 |
{ |
|---|
| 2792 |
Expression * e = NULL; |
|---|
| 2793 |
PtrType ptr_type; |
|---|
| 2794 |
|
|---|
| 2795 |
// First, check for type prefix. |
|---|
| 2796 |
if ( token->value != TOKeof && |
|---|
| 2797 |
peekToken()->value == TOKidentifier && |
|---|
| 2798 |
peekToken()->ident == Id::ptr ) |
|---|
| 2799 |
{ |
|---|
| 2800 |
|
|---|
| 2801 |
ptr_type = isPtrType ( token ); |
|---|
| 2802 |
if ( ptr_type != Default_Ptr ) |
|---|
| 2803 |
{ |
|---|
| 2804 |
if ( operand->dataSize == Default_Ptr ) |
|---|
| 2805 |
operand->dataSize = ptr_type; |
|---|
| 2806 |
else |
|---|
| 2807 |
stmt->error ( "multiple specifications of operand size" ); |
|---|
| 2808 |
} |
|---|
| 2809 |
else |
|---|
| 2810 |
stmt->error ( "unknown operand size '%s'", token->toChars() ); |
|---|
| 2811 |
nextToken(); |
|---|
| 2812 |
nextToken(); |
|---|
| 2813 |
return parseAsmExp(); |
|---|
| 2814 |
} |
|---|
| 2815 |
|
|---|
| 2816 |
TOK tv = token->value; |
|---|
| 2817 |
switch ( tv ) |
|---|
| 2818 |
{ |
|---|
| 2819 |
case TOKidentifier: |
|---|
| 2820 |
if ( token->ident == ident_seg ) |
|---|
| 2821 |
{ |
|---|
| 2822 |
nextToken(); |
|---|
| 2823 |
stmt->error ( "'seg' not supported" ); |
|---|
| 2824 |
e = parseAsmExp(); |
|---|
| 2825 |
} |
|---|
| 2826 |
else if ( token->ident == Id::offset || |
|---|
| 2827 |
token->ident == Id::offsetof ) |
|---|
| 2828 |
{ |
|---|
| 2829 |
if ( token->ident == Id::offset && ! global.params.useDeprecated ) |
|---|
| 2830 |
stmt->error ( "offset deprecated, use offsetof" ); |
|---|
| 2831 |
nextToken(); |
|---|
| 2832 |
e = parseAsmExp(); |
|---|
| 2833 |
e = new AddrExp ( stmt->loc, e ); |
|---|
| 2834 |
} |
|---|
| 2835 |
else |
|---|
| 2836 |
{ |
|---|
| 2837 |
// primary exp |
|---|
| 2838 |
break; |
|---|
| 2839 |
} |
|---|
| 2840 |
return e; |
|---|
| 2841 |
case TOKadd: |
|---|
| 2842 |
case TOKmin: |
|---|
| 2843 |
case TOKnot: |
|---|
| 2844 |
case TOKtilde: |
|---|
| 2845 |
nextToken(); |
|---|
| 2846 |
e = parseUnaExp(); |
|---|
| 2847 |
return intOp ( tv, e, NULL ); |
|---|
| 2848 |
default: |
|---|
| 2849 |
// primary exp |
|---|
| 2850 |
break; |
|---|
| 2851 |
} |
|---|
| 2852 |
return parsePrimaryExp(); |
|---|
| 2853 |
} |
|---|
| 2854 |
|
|---|
| 2855 |
Expression * parsePrimaryExp() |
|---|
| 2856 |
{ |
|---|
| 2857 |
Expression * e; |
|---|
| 2858 |
Identifier * ident = NULL; |
|---|
| 2859 |
|
|---|
| 2860 |
// get rid of short/long prefixes for branches |
|---|
| 2861 |
if (opTakesLabel() && (token->value == TOKint16 || token->value == TOKint64)) |
|---|
| 2862 |
nextToken(); |
|---|
| 2863 |
|
|---|
| 2864 |
switch ( token->value ) |
|---|
| 2865 |
{ |
|---|
| 2866 |
case TOKint32v: |
|---|
| 2867 |
case TOKuns32v: |
|---|
| 2868 |
case TOKint64v: |
|---|
| 2869 |
case TOKuns64v: |
|---|
| 2870 |
// semantic here? |
|---|
| 2871 |
// %% for tok64 really should use 64bit type |
|---|
| 2872 |
e = new IntegerExp ( stmt->loc, token->uns64value, Type::tint64 ); |
|---|
| 2873 |
nextToken(); |
|---|
| 2874 |
break; |
|---|
| 2875 |
case TOKfloat32v: |
|---|
| 2876 |
case TOKfloat64v: |
|---|
| 2877 |
case TOKfloat80v: |
|---|
| 2878 |
// %% need different types? |
|---|
| 2879 |
e = new RealExp ( stmt->loc, token->float80value, Type::tfloat80 ); |
|---|
| 2880 |
nextToken(); |
|---|
| 2881 |
break; |
|---|
| 2882 |
case TOKidentifier: |
|---|
| 2883 |
{ |
|---|
| 2884 |
ident = token->ident; |
|---|
| 2885 |
nextToken(); |
|---|
| 2886 |
|
|---|
| 2887 |
if ( ident == Id::__LOCAL_SIZE ) |
|---|
| 2888 |
{ |
|---|
| 2889 |
return new IdentifierExp ( stmt->loc, ident ); |
|---|
| 2890 |
} |
|---|
| 2891 |
else if ( ident == Id::__dollar ) |
|---|
| 2892 |
{ |
|---|
| 2893 |
do_dollar: |
|---|
| 2894 |
return new IdentifierExp ( stmt->loc, ident ); |
|---|
| 2895 |
} |
|---|
| 2896 |
else |
|---|
| 2897 |
{ |
|---|
| 2898 |
e = new IdentifierExp ( stmt->loc, ident ); |
|---|
| 2899 |
} |
|---|
| 2900 |
|
|---|
| 2901 |
// If this is more than one component ref, it gets complicated: *(&Field + n) |
|---|
| 2902 |
// maybe just do one step at a time.. |
|---|
| 2903 |
// simple case is Type.f -> VarDecl(field) |
|---|
| 2904 |
// actually, DMD only supports on level... |
|---|
| 2905 |
// X.y+Y.z[EBX] is supported, tho.. |
|---|
| 2906 |
// %% doesn't handle properties (check%%) |
|---|
| 2907 |
while ( token->value == TOKdot ) |
|---|
| 2908 |
{ |
|---|
| 2909 |
nextToken(); |
|---|
| 2910 |
if ( token->value == TOKidentifier ) |
|---|
| 2911 |
{ |
|---|
| 2912 |
e = new DotIdExp ( stmt->loc, e, token->ident ); |
|---|
| 2913 |
nextToken(); |
|---|
| 2914 |
} |
|---|
| 2915 |
else |
|---|
| 2916 |
{ |
|---|
| 2917 |
stmt->error ( "expected identifier" ); |
|---|
| 2918 |
return Handled; |
|---|
| 2919 |
} |
|---|
| 2920 |
} |
|---|
| 2921 |
|
|---|
| 2922 |
// check for reg first then dotexp is an error? |
|---|
| 2923 |
if ( e->op == TOKidentifier ) |
|---|
| 2924 |
{ |
|---|
| 2925 |
for ( int i = 0; i < N_Regs; i++ ) |
|---|
| 2926 |
{ |
|---|
| 2927 |
if ( ident == regInfo[i].ident ) |
|---|
| 2928 |
{ |
|---|
| 2929 |
if ( ( Reg ) i == Reg_ST && token->value == TOKlparen ) |
|---|
| 2930 |
{ |
|---|
| 2931 |
nextToken(); |
|---|
| 2932 |
switch ( token->value ) |
|---|
| 2933 |
{ |
|---|
| 2934 |
case TOKint32v: case TOKuns32v: |
|---|
| 2935 |
case TOKint64v: case TOKuns64v: |
|---|
| 2936 |
if ( token->uns64value < 8 ) |
|---|
| 2937 |
e = newRegExp ( ( Reg ) ( Reg_ST + token->uns64value ) ); |
|---|
| 2938 |
else |
|---|
| 2939 |
{ |
|---|
| 2940 |
stmt->error ( "invalid floating point register index" ); |
|---|
| 2941 |
e = Handled; |
|---|
| 2942 |
} |
|---|
| 2943 |
nextToken(); |
|---|
| 2944 |
if ( token->value == TOKrparen ) |
|---|
| 2945 |
nextToken(); |
|---|
| 2946 |
else |
|---|
| 2947 |
stmt->error ( "expected ')'" ); |
|---|
| 2948 |
return e; |
|---|
| 2949 |
default: |
|---|
| 2950 |
break; |
|---|
| 2951 |
} |
|---|
| 2952 |
invalidExpression(); |
|---|
| 2953 |
return Handled; |
|---|
| 2954 |
} |
|---|
| 2955 |
else if ( token->value == TOKcolon ) |
|---|
| 2956 |
{ |
|---|
| 2957 |
nextToken(); |
|---|
| 2958 |
if ( operand->segmentPrefix != Reg_Invalid ) |
|---|
| 2959 |
stmt->error ( "too many segment prefixes" ); |
|---|
| 2960 |
else if ( i >= Reg_CS && i <= Reg_GS ) |
|---|
| 2961 |
operand->segmentPrefix = ( Reg ) i; |
|---|
| 2962 |
else |
|---|
| 2963 |
stmt->error ( "'%s' is not a segment register", ident->string ); |
|---|
| 2964 |
return parseAsmExp(); |
|---|
| 2965 |
} |
|---|
| 2966 |
else |
|---|
| 2967 |
{ |
|---|
| 2968 |
return newRegExp ( ( Reg ) i ); |
|---|
| 2969 |
} |
|---|
| 2970 |
} |
|---|
| 2971 |
} |
|---|
| 2972 |
} |
|---|
| 2973 |
|
|---|
| 2974 |
if ( opTakesLabel() /*opInfo->takesLabel()*/ && e->op == TOKidentifier ) |
|---|
| 2975 |
{ |
|---|
| 2976 |
// DMD uses labels secondarily to other symbols, so check |
|---|
| 2977 |
// if IdentifierExp::semantic won't find anything. |
|---|
| 2978 |
Dsymbol *scopesym; |
|---|
| 2979 |
|
|---|
| 2980 |
if ( ! sc->search ( stmt->loc, ident, & scopesym ) ) |
|---|
| 2981 |
return new DsymbolExp ( stmt->loc, |
|---|
| 2982 |
sc->func->searchLabel ( ident ) ); |
|---|
| 2983 |
} |
|---|
| 2984 |
|
|---|
| 2985 |
e = e->semantic ( sc ); |
|---|
| 2986 |
|
|---|
| 2987 |
// Special case for floating point constant declarations. |
|---|
| 2988 |
if ( e->op == TOKfloat64 ) |
|---|
| 2989 |
{ |
|---|
| 2990 |
Dsymbol * sym = sc->search ( stmt->loc, ident, NULL ); |
|---|
| 2991 |
if ( sym ) |
|---|
| 2992 |
{ |
|---|
| 2993 |
VarDeclaration *v = sym->isVarDeclaration(); |
|---|
| 2994 |
if ( v ) |
|---|
| 2995 |
{ |
|---|
| 2996 |
Expression *ve = new VarExp ( stmt->loc, v ); |
|---|
| 2997 |
ve->type = e->type; |
|---|
| 2998 |
e = ve; |
|---|
| 2999 |
} |
|---|
| 3000 |
} |
|---|
| 3001 |
} |
|---|
| 3002 |
return e; |
|---|
| 3003 |
} |
|---|
| 3004 |
break; |
|---|
| 3005 |
case TOKdollar: |
|---|
| 3006 |
nextToken(); |
|---|
| 3007 |
ident = Id::__dollar; |
|---|
| 3008 |
goto do_dollar; |
|---|
| 3009 |
break; |
|---|
| 3010 |
default: |
|---|
| 3011 |
if ( op == Op_FMath0 || op == Op_FdST0ST1 || op == Op_FMath ) |
|---|
| 3012 |
return Handled; |
|---|
| 3013 |
invalidExpression(); |
|---|
| 3014 |
return Handled; |
|---|
| 3015 |
} |
|---|
| 3016 |
return e; |
|---|
| 3017 |
} |
|---|
| 3018 |
|
|---|
| 3019 |
void doAlign() |
|---|
| 3020 |
{ |
|---|
| 3021 |
// .align bits vs. bytes... |
|---|
| 3022 |
// apparently a.out platforms use bits instead of bytes... |
|---|
| 3023 |
|
|---|
| 3024 |
// parse primary: DMD allows 'MyAlign' (const int) but not '2+2' |
|---|
| 3025 |
// GAS is padding with NOPs last time I checked. |
|---|
| 3026 |
Expression * e = parseAsmExp()->optimize ( WANTvalue | WANTinterpret ); |
|---|
| 3027 |
uinteger_t align = e->toUInteger(); |
|---|
| 3028 |
|
|---|
| 3029 |
if ( ( align & ( align - 1 ) ) == 0 ) |
|---|
| 3030 |
{ |
|---|
| 3031 |
//FIXME: This printf is not portable. The use of `align` varies from system to system; |
|---|
| 3032 |
// on i386 using a.out, .align `n` will align on a 2^`n` boundary instead of an `n` boundary |
|---|
| 3033 |
#ifdef HAVE_GAS_BALIGN_AND_P2ALIGN |
|---|
| 3034 |
insnTemplate << ".balign\t" << align; |
|---|
| 3035 |
#else |
|---|
| 3036 |
insnTemplate << ".align\t" << align; |
|---|
| 3037 |
#endif |
|---|
| 3038 |
} |
|---|
| 3039 |
else |
|---|
| 3040 |
{ |
|---|
| 3041 |
stmt->error ( "alignment must be a power of 2, not %u", ( unsigned ) align ); |
|---|
| 3042 |
} |
|---|
| 3043 |
|
|---|
| 3044 |
setAsmCode(); |
|---|
| 3045 |
} |
|---|
| 3046 |
|
|---|
| 3047 |
void doEven() |
|---|
| 3048 |
{ |
|---|
| 3049 |
// .align for GAS is in bits, others probably use bytes.. |
|---|
| 3050 |
#ifdef HAVE_GAS_BALIGN_AND_P2ALIGN |
|---|
| 3051 |
insnTemplate << ".align\t2"; |
|---|
| 3052 |
#else |
|---|
| 3053 |
insnTemplate << ".align\t2"; |
|---|
| 3054 |
#endif |
|---|
| 3055 |
setAsmCode(); |
|---|
| 3056 |
} |
|---|
| 3057 |
|
|---|
| 3058 |
void doNaked() |
|---|
| 3059 |
{ |
|---|
| 3060 |
// %% can we assume sc->func != 0? |
|---|
| 3061 |
sc->func->naked = 1; |
|---|
| 3062 |
} |
|---|
| 3063 |
|
|---|
| 3064 |
void doData() |
|---|
| 3065 |
{ |
|---|
| 3066 |
static const char * directives[] = { ".byte", ".short", ".long", ".long", |
|---|
| 3067 |
"", "", "" |
|---|
| 3068 |
}; |
|---|
| 3069 |
// FIXME |
|---|
| 3070 |
/* |
|---|
| 3071 |
machine_mode mode; |
|---|
| 3072 |
|
|---|
| 3073 |
insnTemplate->writestring((char*) directives[op - Op_db]); |
|---|
| 3074 |
insnTemplate->writebyte(' '); |
|---|
| 3075 |
|
|---|
| 3076 |
do { |
|---|
| 3077 |
// DMD is pretty strict here, not even constant expressions are allowed.. |
|---|
| 3078 |
switch (op) { |
|---|
| 3079 |
case Op_db: |
|---|
| 3080 |
case Op_ds: |
|---|
| 3081 |
case Op_di: |
|---|
| 3082 |
case Op_dl: |
|---|
| 3083 |
if (token->value == TOKint32v || token->value == TOKuns32v || |
|---|
| 3084 |
token->value == TOKint64v || token->value == TOKuns64v) { |
|---|
| 3085 |
// As per usual with GNU, assume at least 32-bit host |
|---|
| 3086 |
if (op != Op_dl) |
|---|
| 3087 |
insnTemplate->printf("%u", (d_uns32) token->uns64value); |
|---|
| 3088 |
else { |
|---|
| 3089 |
// Output two .longS. GAS has .quad, but would have to rely on 'L' format .. |
|---|
| 3090 |
// just need to use HOST_WIDE_INT_PRINT_DEC |
|---|
| 3091 |
insnTemplate->printf("%u,%u", |
|---|
| 3092 |
(d_uns32) token->uns64value, (d_uns32) (token->uns64value >> 32)); |
|---|
| 3093 |
} |
|---|
| 3094 |
} else { |
|---|
| 3095 |
stmt->error("expected integer constant"); |
|---|
| 3096 |
} |
|---|
| 3097 |
break; |
|---|
| 3098 |
case Op_df: |
|---|
| 3099 |
mode = SFmode; |
|---|
| 3100 |
goto do_float; |
|---|
| 3101 |
case Op_dd: |
|---|
| 3102 |
mode = DFmode; |
|---|
| 3103 |
goto do_float; |
|---|
| 3104 |
case Op_de: |
|---|
| 3105 |
#ifndef TARGET_80387 |
|---|
| 3106 |
#define XFmode TFmode |
|---|
| 3107 |
#endif |
|---|
| 3108 |
mode = XFmode; // not TFmode |
|---|
| 3109 |
// drop through |
|---|
| 3110 |
do_float: |
|---|
| 3111 |
if (token->value == TOKfloat32v || token->value == TOKfloat64v || |
|---|
| 3112 |
token->value == TOKfloat80v) { |
|---|
| 3113 |
long words[3]; |
|---|
| 3114 |
real_to_target(words, & token->float80value.rv(), mode); |
|---|
| 3115 |
// don't use directives..., just use .long like GCC |
|---|
| 3116 |
insnTemplate->printf(".long\t%u", words[0]); |
|---|
| 3117 |
if (mode != SFmode) |
|---|
| 3118 |
insnTemplate->printf(",%u", words[1]); |
|---|
| 3119 |
// DMD outputs 10 bytes, so we need to switch to .short here |
|---|
| 3120 |
if (mode == XFmode) |
|---|
| 3121 |
insnTemplate->printf("\n\t.short\t%u", words[2]); |
|---|
| 3122 |
} else { |
|---|
| 3123 |
stmt->error("expected float constant"); |
|---|
| 3124 |
} |
|---|
| 3125 |
break; |
|---|
| 3126 |
default: |
|---|
| 3127 |
abort(); |
|---|
| 3128 |
} |
|---|
| 3129 |
|
|---|
| 3130 |
nextToken(); |
|---|
| 3131 |
if (token->value == TOKcomma) { |
|---|
| 3132 |
insnTemplate->writebyte(','); |
|---|
| 3133 |
nextToken(); |
|---|
| 3134 |
} else if (token->value == TOKeof) { |
|---|
| 3135 |
break; |
|---|
| 3136 |
} else { |
|---|
| 3137 |
stmt->error("expected comma"); |
|---|
| 3138 |
} |
|---|
| 3139 |
} while (1); |
|---|
| 3140 |
|
|---|
| 3141 |
setAsmCode();*/ |
|---|
| 3142 |
} |
|---|
| 3143 |
}; |
|---|
| 3144 |
|
|---|
| 3145 |
#if D_GCC_VER < 40 |
|---|
| 3146 |
// struct rtx was modified for c++; this macro from rtl.h needs to |
|---|
| 3147 |
// be modified accordingly. |
|---|
| 3148 |
#undef XEXP |
|---|
| 3149 |
#define XEXP(RTX, N) (RTL_CHECK2 (RTX, N, 'e', 'u').rt_rtx) |
|---|
| 3150 |
#endif |
|---|
| 3151 |
|
|---|
| 3152 |
// FIXME |
|---|
| 3153 |
#define HOST_WIDE_INT long |
|---|
| 3154 |
bool getFrameRelativeValue ( LLValue* decl, HOST_WIDE_INT * result ) |
|---|
| 3155 |
{ |
|---|
| 3156 |
assert ( 0 ); |
|---|
| 3157 |
// FIXME |
|---|
| 3158 |
// // Using this instead of DECL_RTL for struct args seems like a |
|---|
| 3159 |
// // good way to get hit by a truck because it may not agree with |
|---|
| 3160 |
// // non-asm access, but asm code wouldn't know what GCC does anyway. */ |
|---|
| 3161 |
// rtx r = DECL_INCOMING_RTL(decl); |
|---|
| 3162 |
// rtx e1, e2; |
|---|
| 3163 |
// |
|---|
| 3164 |
// // Local variables don't have DECL_INCOMING_RTL |
|---|
| 3165 |
// if (r == NULL_RTX) |
|---|
| 3166 |
// r = DECL_RTL(decl); |
|---|
| 3167 |
// |
|---|
| 3168 |
// if (r != NULL_RTX && GET_CODE(r) == MEM /* && r->frame_related */ ) { |
|---|
| 3169 |
// r = XEXP(r, 0); |
|---|
| 3170 |
// if (GET_CODE(r) == PLUS) { |
|---|
| 3171 |
// e1 = XEXP(r, 0); |
|---|
| 3172 |
// e2 = XEXP(r, 1); |
|---|
| 3173 |
// if (e1 == virtual_incoming_args_rtx && GET_CODE(e2) == CONST_INT) { |
|---|
| 3174 |
// *result = INTVAL(e2) + 8; // %% 8 is 32-bit specific... |
|---|
| 3175 |
// return true; |
|---|
| 3176 |
// } else if (e1 == virtual_stack_vars_rtx && GET_CODE(e2) == CONST_INT) { |
|---|
| 3177 |
// *result = INTVAL(e2); // %% 8 is 32-bit specific... |
|---|
| 3178 |
// return true; |
|---|
| 3179 |
// } |
|---|
| 3180 |
// } else if (r == virtual_incoming_args_rtx) { |
|---|
| 3181 |
// *result = 8; |
|---|
| 3182 |
// return true; // %% same as above |
|---|
| 3183 |
// } |
|---|
| 3184 |
// // shouldn't have virtual_stack_vars_rtx by itself |
|---|
| 3185 |
// } |
|---|
| 3186 |
// |
|---|
| 3187 |
return false; |
|---|
| 3188 |
} |
|---|
| 3189 |
|
|---|
| 3190 |
|
|---|
| 3191 |
struct AsmParser : public AsmParserCommon |
|---|
| 3192 |
{ |
|---|
| 3193 |
virtual void run ( Scope* sc, AsmStatement* asmst ) |
|---|
| 3194 |
{ |
|---|
| 3195 |
AsmProcessor ap ( sc, asmst ); |
|---|
| 3196 |
ap.run(); |
|---|
| 3197 |
} |
|---|
| 3198 |
|
|---|
| 3199 |
virtual std::string getRegName ( int i ) |
|---|
| 3200 |
{ |
|---|
| 3201 |
return regInfo[i].gccName; |
|---|
| 3202 |
} |
|---|
| 3203 |
}; |
|---|
| 3204 |
|
|---|
| 3205 |
} |
|---|