1: 
   2: /*
   3:  * Copyright (c) 1992-1999 by Symantec
   4:  * Copyright (c) 1999-2011 by Digital Mars
   5:  * All Rights Reserved
   6:  * http://www.digitalmars.com
   7:  * http://www.dsource.org/projects/dmd/browser/branches/dmd-1.x/src/iasm.c
   8:  * http://www.dsource.org/projects/dmd/browser/trunk/src/iasm.c
   9:  * Written by Mike Cote, John Micco and Walter Bright
  10:  * D version by Walter Bright
  11:  *
  12:  * This source file is made available for personal use
  13:  * only. The license is in /dmd/src/dmd/backendlicense.txt
  14:  * For any other uses, please contact Digital Mars.
  15:  */
  16: 
  17: // Inline assembler for the D programming language compiler
  18: 
  19: #include        <ctype.h>
  20: #include        <stdlib.h>
  21: #include        <stdio.h>
  22: #include        <string.h>
  23: #include        <time.h>
  24: static char __file__[] = __FILE__;      /* for tassert.h                */
  25: #include        "tassert.h"
  26: #include        <setjmp.h>
  27: #if __DMC__
  28: #undef setjmp
  29: #include        <limits.h>
  30: #endif
  31: 
  32: 
  33: // D compiler
  34: #include        "mars.h"
  35: #include        "lexer.h"
  36: #include        "mtype.h"
  37: #include        "statement.h"
  38: #include        "id.h"
  39: #include        "declaration.h"
  40: #include        "scope.h"
  41: #include        "init.h"
  42: #include        "enum.h"
  43: #include        "module.h"
  44: 
  45: // C/C++ compiler
  46: #define SCOPE_H 1               // avoid conflicts with D's Scope
  47: #include        "cc.h"
  48: #include        "token.h"
  49: #include        "global.h"
  50: #include        "el.h"
  51: #include        "type.h"
  52: #include        "oper.h"
  53: #include        "code.h"
  54: #include        "iasm.h"
  55: 
  56: // I32 isn't set correctly yet because this is the front end, and I32
  57: // is a backend flag
  58: #undef I16
  59: #undef I32
  60: #undef I64
  61: #define I16 0
  62: #define I32 (global.params.is64bit == 0)
  63: #define I64 (global.params.is64bit == 1)
  64: 
  65: //#define EXTRA_DEBUG 1
  66: 
  67: #undef ADDFWAIT
  68: #define ADDFWAIT()      0
  69: 
  70: // Error numbers
  71: enum ASMERRMSGS
  72: {
  73:     EM_bad_float_op,
  74:     EM_bad_addr_mode,
  75:     EM_align,
  76:     EM_opcode_exp,
  77:     EM_prefix,
  78:     EM_eol,
  79:     EM_bad_operand,
  80:     EM_bad_integral_operand,
  81:     EM_ident_exp,
  82:     EM_not_struct,
  83:     EM_nops_expected,
  84:     EM_bad_op,
  85:     EM_const_init,
  86:     EM_undefined,
  87:     EM_pointer,
  88:     EM_colon,
  89:     EM_rbra,
  90:     EM_rpar,
  91:     EM_ptr_exp,
  92:     EM_num,
  93:     EM_float,
  94:     EM_char,
  95:     EM_label_expected,
  96:     EM_uplevel,
  97:     EM_type_as_operand,
  98:     EM_invalid_64bit_opcode,
  99: };
 100: 
 101: const char *asmerrmsgs[] =
 102: {
 103:     "unknown operand for floating point instruction",
 104:     "bad addr mode",
 105:     "align %d must be a power of 2",
 106:     "opcode expected, not %s",
 107:     "prefix",
 108:     "end of instruction",
 109:     "bad operand",
 110:     "bad integral operand",
 111:     "identifier expected",
 112:     "not struct",
 113:     "%u operands found for %s instead of the expected %u",
 114:     "bad type/size of operands '%s'",
 115:     "constant initializer expected",
 116:     "undefined identifier '%s'",
 117:     "pointer",
 118:     "colon",
 119:     "] expected instead of '%s'",
 120:     ") expected instead of '%s'",
 121:     "ptr expected",
 122:     "integer expected",
 123:     "floating point expected",
 124:     "character is truncated",
 125:     "label expected",
 126:     "uplevel nested reference to variable %s",
 127:     "cannot use type %s as an operand",
 128:     "opcode %s is unavailable in 64bit mode"
 129: };
 130: 
 131: // Additional tokens for the inline assembler
 132: typedef enum
 133: {
 134:     ASMTKlocalsize = TOKMAX + 1,
 135:     ASMTKdword,
 136:     ASMTKeven,
 137:     ASMTKfar,
 138:     ASMTKnaked,
 139:     ASMTKnear,
 140:     ASMTKptr,
 141:     ASMTKqword,
 142:     ASMTKseg,
 143:     ASMTKword,
 144:     ASMTKmax = ASMTKword-(TOKMAX+1)+1
 145: } ASMTK;
 146: 
 147: static const char *apszAsmtk[ASMTKmax] = {
 148:         "__LOCAL_SIZE",
 149:         "dword",
 150:         "even",
 151:         "far",
 152:         "naked",
 153:         "near",
 154:         "ptr",
 155:         "qword",
 156:         "seg",
 157:         "word",
 158: };
 159: 
 160: struct ASM_STATE
 161: {
 162:         unsigned char ucItype;  // Instruction type
 163: #define ITprefix        0x10    // special prefix
 164: #define ITjump          0x20    // jump instructions CALL, Jxx and LOOPxx
 165: #define ITimmed         0x30    // value of an immediate operand controls
 166:                                 // code generation
 167: #define ITopt           0x40    // not all operands are required
 168: #define ITshift         0x50    // rotate and shift instructions
 169: #define ITfloat         0x60    // floating point coprocessor instructions
 170: #define ITdata          0x70    // DB, DW, DD, DQ, DT pseudo-ops
 171: #define ITaddr          0x80    // DA (define addresss) pseudo-op
 172: #define ITMASK          0xF0
 173: #define ITSIZE          0x0F    // mask for size
 174: 
 175:         Loc loc;
 176:         unsigned char bInit;
 177:         LabelDsymbol *psDollar;
 178:         Dsymbol *psLocalsize;
 179:         jmp_buf env;
 180:         unsigned char bReturnax;
 181:         AsmStatement *statement;
 182:         Scope *sc;
 183: };
 184: 
 185: ASM_STATE asmstate;
 186: 
 187: static Token *asmtok;
 188: static enum TOK tok_value;
 189: //char debuga = 1;
 190: 
 191: // From ptrntab.c
 192: const char *asm_opstr(OP *pop);
 193: OP *asm_op_lookup(const char *s);
 194: void init_optab();
 195: 
 196: static unsigned char asm_TKlbra_seen = FALSE;
 197: 
 198: typedef struct
 199: {
 200:         char regstr[6];
 201:         unsigned char val;
 202:         opflag_t ty;
 203: } REG;
 204: 
 205: static REG regFp =      { "ST", 0, _st };
 206: 
 207: static REG aregFp[] = {
 208:         { "ST(0)", 0, _sti },
 209:         { "ST(1)", 1, _sti },
 210:         { "ST(2)", 2, _sti },
 211:         { "ST(3)", 3, _sti },
 212:         { "ST(4)", 4, _sti },
 213:         { "ST(5)", 5, _sti },
 214:         { "ST(6)", 6, _sti },
 215:         { "ST(7)", 7, _sti }
 216: };
 217: #define _AL             0
 218: #define _AH             4
 219: #define _AX             0
 220: #define _EAX            0
 221: #define _BL             3
 222: #define _BH             7
 223: #define _BX             3
 224: #define _EBX            3
 225: #define _CL             1
 226: #define _CH             5
 227: #define _CX             1
 228: #define _ECX            1
 229: #define _DL             2
 230: #define _DH             6
 231: #define _DX             2
 232: #define _EDX            2
 233: #define _BP             5
 234: #define _EBP            5
 235: #define _SP             4
 236: #define _ESP            4
 237: #define _DI             7
 238: #define _EDI            7
 239: #define _SI             6
 240: #define _ESI            6
 241: #define _ES             0
 242: #define _CS             1
 243: #define _SS             2
 244: #define _DS             3
 245: #define _GS             5
 246: #define _FS             4
 247: 
 248: static REG regtab[] =
 249: {
 250: "AL",   _AL,    _r8 | _al,
 251: "AH",   _AH,    _r8,
 252: "AX",   _AX,    _r16 | _ax,
 253: "EAX",  _EAX,   _r32 | _eax,
 254: "BL",   _BL,    _r8,
 255: "BH",   _BH,    _r8,
 256: "BX",   _BX,    _r16,
 257: "EBX",  _EBX,   _r32,
 258: "CL",   _CL,    _r8 | _cl,
 259: "CH",   _CH,    _r8,
 260: "CX",   _CX,    _r16,
 261: "ECX",  _ECX,   _r32,
 262: "DL",   _DL,    _r8,
 263: "DH",   _DH,    _r8,
 264: "DX",   _DX,    _r16 | _dx,
 265: "EDX",  _EDX,   _r32,
 266: "BP",   _BP,    _r16,
 267: "EBP",  _EBP,   _r32,
 268: "SP",   _SP,    _r16,
 269: "ESP",  _ESP,   _r32,
 270: "DI",   _DI,    _r16,
 271: "EDI",  _EDI,   _r32,
 272: "SI",   _SI,    _r16,
 273: "ESI",  _ESI,   _r32,
 274: "ES",   _ES,    _seg | _es,
 275: "CS",   _CS,    _seg | _cs,
 276: "SS",   _SS,    _seg | _ss ,
 277: "DS",   _DS,    _seg | _ds,
 278: "GS",   _GS,    _seg | _gs,
 279: "FS",   _FS,    _seg | _fs,
 280: "CR0",  0,      _special | _crn,
 281: "CR2",  2,      _special | _crn,
 282: "CR3",  3,      _special | _crn,
 283: "CR4",  4,      _special | _crn,
 284: "DR0",  0,      _special | _drn,
 285: "DR1",  1,      _special | _drn,
 286: "DR2",  2,      _special | _drn,
 287: "DR3",  3,      _special | _drn,
 288: "DR4",  4,      _special | _drn,
 289: "DR5",  5,      _special | _drn,
 290: "DR6",  6,      _special | _drn,
 291: "DR7",  7,      _special | _drn,
 292: "TR3",  3,      _special | _trn,
 293: "TR4",  4,      _special | _trn,
 294: "TR5",  5,      _special | _trn,
 295: "TR6",  6,      _special | _trn,
 296: "TR7",  7,      _special | _trn,
 297: "MM0",  0,      _mm,
 298: "MM1",  1,      _mm,
 299: "MM2",  2,      _mm,
 300: "MM3",  3,      _mm,
 301: "MM4",  4,      _mm,
 302: "MM5",  5,      _mm,
 303: "MM6",  6,      _mm,
 304: "MM7",  7,      _mm,
 305: "XMM0", 0,      _xmm | _xmm0,
 306: "XMM1", 1,      _xmm,
 307: "XMM2", 2,      _xmm,
 308: "XMM3", 3,      _xmm,
 309: "XMM4", 4,      _xmm,
 310: "XMM5", 5,      _xmm,
 311: "XMM6", 6,      _xmm,
 312: "XMM7", 7,      _xmm,
 313: };
 314: 
 315: // 64 bit only registers
 316: #define _RAX    0
 317: #define _RBX    3
 318: #define _RCX    1
 319: #define _RDX    2
 320: #define _RSI    6
 321: #define _RDI    7
 322: #define _RBP    5
 323: #define _RSP    4
 324: #define _R8     8
 325: #define _R9     9
 326: #define _R10    10
 327: #define _R11    11
 328: #define _R12    12
 329: #define _R13    13
 330: #define _R14    14
 331: #define _R15    15
 332: 
 333: #define _R8D    8
 334: #define _R9D    9
 335: #define _R10D   10
 336: #define _R11D   11
 337: #define _R12D   12
 338: #define _R13D   13
 339: #define _R14D   14
 340: #define _R15D   15
 341: 
 342: #define _R8W    8
 343: #define _R9W    9
 344: #define _R10W   10
 345: #define _R11W   11
 346: #define _R12W   12
 347: #define _R13W   13
 348: #define _R14W   13
 349: #define _R15W   15
 350: 
 351: #define _SIL    6
 352: #define _DIL    7
 353: #define _BPL    5
 354: #define _SPL    4
 355: #define _R8B    8
 356: #define _R9B    9
 357: #define _R10B   10
 358: #define _R11B   11
 359: #define _R12B   12
 360: #define _R13B   13
 361: #define _R14B   14
 362: #define _R15B   15
 363: 
 364: static REG regtab64[] =
 365: {
 366: "RAX",  _RAX,   _r64 | _rax,
 367: "RBX",  _RBX,   _r64,
 368: "RCX",  _RCX,   _r64,
 369: "RDX",  _RDX,   _r64,
 370: "RSI",  _RSI,   _r64,
 371: "RDI",  _RDI,   _r64,
 372: "RBP",  _RBP,   _r64,
 373: "RSP",  _RSP,   _r64,
 374: "R8",   _R8,    _r64,
 375: "R9",   _R9,    _r64,
 376: "R10",  _R10,   _r64,
 377: "R11",  _R11,   _r64,
 378: "R12",  _R12,   _r64,
 379: "R13",  _R13,   _r64,
 380: "R14",  _R14,   _r64,
 381: "R15",  _R15,   _r64,
 382: 
 383: "R8D",  _R8D,   _r32,
 384: "R9D",  _R9D,   _r32,
 385: "R10D", _R10D,  _r32,
 386: "R11D", _R11D,  _r32,
 387: "R12D", _R12D,  _r32,
 388: "R13D", _R13D,  _r32,
 389: "R14D", _R14D,  _r32,
 390: "R15D", _R15D,  _r32,
 391: 
 392: "R8W",  _R8W,   _r16,
 393: "R9W",  _R9W,   _r16,
 394: "R10W", _R10W,  _r16,
 395: "R11W", _R11W,  _r16,
 396: "R12W", _R12W,  _r16,
 397: "R13W", _R13W,  _r16,
 398: "R14W", _R14W,  _r16,
 399: "R15W", _R15W,  _r16,
 400: 
 401: "SIL",  _SIL,   _r8,
 402: "DIL",  _DIL,   _r8,
 403: "BPL",  _BPL,   _r8,
 404: "SPL",  _SPL,   _r8,
 405: "R8B",  _R8B,   _r8,
 406: "R9B",  _R9B,   _r8,
 407: "R10B", _R10B,  _r8,
 408: "R11B", _R11B,  _r8,
 409: "R12B", _R12B,  _r8,
 410: "R13B", _R13B,  _r8,
 411: "R14B", _R14B,  _r8,
 412: "R15B", _R15B,  _r8,
 413: 
 414: "XMM8",   8,    _xmm,
 415: "XMM9",   9,    _xmm,
 416: "XMM10", 10,    _xmm,
 417: "XMM11", 11,    _xmm,
 418: "XMM12", 12,    _xmm,
 419: "XMM13", 13,    _xmm,
 420: "XMM14", 14,    _xmm,
 421: "XMM15", 15,    _xmm,
 422: };
 423: 
 424: typedef enum {
 425:     ASM_JUMPTYPE_UNSPECIFIED,
 426:     ASM_JUMPTYPE_SHORT,
 427:     ASM_JUMPTYPE_NEAR,
 428:     ASM_JUMPTYPE_FAR
 429: } ASM_JUMPTYPE;             // ajt
 430: 
 431: typedef struct opnd
 432: {
 433:         REG *base;              // if plain register
 434:         REG *pregDisp1;         // if [register1]
 435:         REG *pregDisp2;
 436:         REG *segreg;            // if segment override
 437:         char indirect;          // if had a '*' or '->'
 438:         char bOffset;           // if 'offset' keyword
 439:         char bSeg;              // if 'segment' keyword
 440:         char bPtr;              // if 'ptr' keyword
 441:         unsigned uchMultiplier; // register multiplier; valid values are 0,1,2,4,8
 442:         opflag_t usFlags;
 443:         Dsymbol *s;
 444:         targ_llong disp;
 445:         long double real;
 446:         Type *ptype;
 447:         ASM_JUMPTYPE ajt;
 448: } OPND;
 449: 
 450: //
 451: // Exported functions called from the compiler
 452: //
 453: int asm_state(int iFlags);
 454: void iasm_term();
 455: 
 456: //
 457: // Local functions defined and only used here
 458: //
 459: STATIC OPND *asm_add_exp();
 460: STATIC OPND *opnd_calloc();
 461: STATIC void opnd_free(OPND *popnd);
 462: STATIC OPND *asm_and_exp();
 463: STATIC OPND *asm_cond_exp();
 464: STATIC opflag_t asm_determine_operand_flags(OPND *popnd);
 465: code *asm_genloc(Loc loc, code *c);
 466: int asm_getnum();
 467: 
 468: STATIC void asmerr(const char *, ...);
 469: STATIC void asmerr(int, ...);
 470: #pragma SC noreturn(asmerr)
warning C4068: unknown pragma
471: 472: STATIC OPND *asm_equal_exp(); 473: STATIC OPND *asm_inc_or_exp(); 474: STATIC OPND *asm_log_and_exp(); 475: STATIC OPND *asm_log_or_exp(); 476: STATIC char asm_length_type_size(OPND *popnd); 477: STATIC void asm_token(); 478: STATIC void asm_token_trans(Token *tok); 479: STATIC unsigned char asm_match_flags(opflag_t usOp , opflag_t usTable ); 480: STATIC unsigned char asm_match_float_flags(opflag_t usOp, opflag_t usTable); 481: STATIC void asm_make_modrm_byte( 482: #ifdef DEBUG 483: unsigned char *puchOpcode, unsigned *pusIdx, 484: #endif 485: code *pc, 486: unsigned usFlags, 487: OPND *popnd, OPND *popnd2); 488: STATIC regm_t asm_modify_regs(PTRNTAB ptb, OPND *popnd1, OPND *popnd2); 489: STATIC void asm_output_flags(opflag_t usFlags); 490: STATIC void asm_output_popnd(OPND *popnd); 491: STATIC unsigned asm_type_size(Type * ptype); 492: STATIC opflag_t asm_float_type_size(Type * ptype, opflag_t *pusFloat); 493: STATIC OPND *asm_mul_exp(); 494: STATIC OPND *asm_br_exp(); 495: STATIC OPND *asm_primary_exp(); 496: STATIC OPND *asm_prim_post(OPND *); 497: STATIC OPND *asm_rel_exp(); 498: STATIC OPND *asm_shift_exp(); 499: STATIC OPND *asm_una_exp(); 500: STATIC OPND *asm_xor_exp(); 501: STATIC void *link_alloc(size_t, void *); 502: STATIC void asm_chktok(enum TOK toknum, unsigned errnum); 503: STATIC code *asm_db_parse(OP *pop); 504: STATIC code *asm_da_parse(OP *pop); 505: 506: unsigned compute_hashkey(char *); 507: 508: 509: /******************************* 510: */ 511: 512: STATIC OPND *opnd_calloc() 513: { OPND *o; 514: 515: o = new OPND(); 516: memset(o, 0, sizeof(*o)); 517: return o; 518: } 519: 520: /******************************* 521: */ 522: 523: STATIC void opnd_free(OPND *o) 524: { 525: if (o) 526: { 527: delete o; 528: } 529: } 530: 531: /******************************* 532: */ 533: 534: STATIC void asm_chktok(enum TOK toknum,unsigned errnum) 535: { 536: if (tok_value == toknum) 537: asm_token(); // scan past token 538: else 539: /* When we run out of tokens, asmtok is NULL. 540: * But when this happens when a ';' was hit. 541: */ 542: asmerr(errnum, asmtok ? asmtok->toChars() : ";"); 543: } 544: 545: 546: /******************************* 547: */ 548: 549: STATIC PTRNTAB asm_classify(OP *pop, OPND *popnd1, OPND *popnd2, OPND *popnd3, 550: unsigned *pusNumops) 551: { 552: unsigned usNumops; 553: unsigned usActual; 554: PTRNTAB ptbRet = { NULL }; 555: opflag_t opflags1 = 0 ; 556: opflag_t opflags2 = 0; 557: opflag_t opflags3 = 0; 558: char bFake = FALSE; 559: char bInvalid64bit = FALSE; 560: 561: unsigned char bMatch1, bMatch2, bMatch3, bRetry = FALSE; 562: 563: // How many arguments are there? the parser is strictly left to right 564: // so this should work. 565: 566: if (!popnd1) 567: usNumops = 0; 568: else 569: { 570: popnd1->usFlags = opflags1 = asm_determine_operand_flags(popnd1); 571: if (!popnd2) 572: usNumops = 1; 573: else 574: { 575: popnd2->usFlags = opflags2 = asm_determine_operand_flags(popnd2); 576: if (!popnd3) 577: usNumops = 2; 578: else 579: { 580: popnd3->usFlags = opflags3 = asm_determine_operand_flags(popnd3); 581: usNumops = 3; 582: } 583: } 584: } 585: 586: // Now check to insure that the number of operands is correct 587: usActual = (pop->usNumops & ITSIZE); 588: if (usActual != usNumops && asmstate.ucItype != ITopt && 589: asmstate.ucItype != ITfloat) 590: { 591: PARAM_ERROR: 592: asmerr(EM_nops_expected, usNumops, asm_opstr(pop), usActual); 593: } 594: if (usActual < usNumops) 595: *pusNumops = usActual; 596: else 597: *pusNumops = usNumops; 598: // 599: // The number of arguments matches, now check to find the opcode 600: // in the associated opcode table 601: // 602: RETRY: 603: //printf("usActual = %d\n", usActual); 604: switch (usActual) 605: { 606: case 0: 607: if (I64 && (pop->ptb.pptb0->usFlags & _i64_bit)) 608: asmerr( EM_invalid_64bit_opcode, asm_opstr(pop)); // illegal opcode in 64bit mode 609: 610: ptbRet = pop->ptb; 611: 612: goto RETURN_IT; 613: 614: case 1: 615: { //printf("opflags1 = "); asm_output_flags(opflags1); printf("\n"); 616: PTRNTAB1 *table1; 617: for (table1 = pop->ptb.pptb1; table1->usOpcode != ASM_END; 618: table1++) 619: { 620: //printf("table = "); asm_output_flags(table1->usOp1); printf("\n"); 621: bMatch1 = asm_match_flags(opflags1, table1->usOp1); 622: //printf("bMatch1 = x%x\n", bMatch1); 623: if (bMatch1) 624: { if (table1->usOpcode == 0x68 &&
warning C6240: (<expression> && <non-zero constant>) always evaluates to the result of <expression>. Did you intend to use the bitwise-and operator?
625: !I16 && 626: table1->usOp1 == _imm16 627: ) 628: // Don't match PUSH imm16 in 32 bit code 629: continue; 630: 631: // Check if match is invalid in 64bit mode 632: if (I64 && (table1->usFlags & _i64_bit)) 633: { 634: bInvalid64bit = TRUE; 635: continue; 636: } 637: 638: break; 639: } 640: if ((asmstate.ucItype == ITimmed) && 641: asm_match_flags(opflags1, 642: CONSTRUCT_FLAGS(_8 | _16 | _32, _imm, _normal, 643: 0)) && 644: popnd1->disp == table1->usFlags) 645: break; 646: if ((asmstate.ucItype == ITopt || 647: asmstate.ucItype == ITfloat) && 648: !usNumops && 649: !table1->usOp1) 650: { 651: if (usNumops > 1) 652: goto PARAM_ERROR; 653: break; 654: } 655: } 656: if (table1->usOpcode == ASM_END) 657: { 658: #ifdef DEBUG 659: if (debuga) 660: { printf("\t%s\t", asm_opstr(pop)); 661: if (popnd1) 662: asm_output_popnd(popnd1); 663: if (popnd2) { 664: printf(","); 665: asm_output_popnd(popnd2); 666: } 667: if (popnd3) { 668: printf(","); 669: asm_output_popnd(popnd3); 670: } 671: printf("\n"); 672: 673: printf("OPCODE mism = "); 674: if (popnd1) 675: asm_output_flags(popnd1->usFlags); 676: else 677: printf("NONE"); 678: printf("\n"); 679: } 680: #endif 681: TYPE_SIZE_ERROR: 682: if (popnd1 && ASM_GET_aopty(popnd1->usFlags) != _reg) 683: { 684: opflags1 = popnd1->usFlags |= _anysize; 685: if (asmstate.ucItype == ITjump) 686: { 687: if (bRetry && popnd1->s && !popnd1->s->isLabel()) 688: { 689: asmerr(EM_label_expected, popnd1->s->toChars()); 690: } 691: 692: popnd1->usFlags |= CONSTRUCT_FLAGS(0, 0, 0, 693: _fanysize); 694: } 695: } 696: if (popnd2 && ASM_GET_aopty(popnd2->usFlags) != _reg) { 697: opflags2 = popnd2->usFlags |= (_anysize); 698: if (asmstate.ucItype == ITjump) 699: popnd2->usFlags |= CONSTRUCT_FLAGS(0, 0, 0, 700: _fanysize); 701: } 702: if (popnd3 && ASM_GET_aopty(popnd3->usFlags) != _reg) { 703: opflags3 = popnd3->usFlags |= (_anysize); 704: if (asmstate.ucItype == ITjump) 705: popnd3->usFlags |= CONSTRUCT_FLAGS(0, 0, 0, 706: _fanysize); 707: } 708: if (bRetry) 709: { 710: if(bInvalid64bit) 711: asmerr("operand for '%s' invalid in 64bit mode", asm_opstr(pop)); 712: else 713: asmerr(EM_bad_op, asm_opstr(pop)); // illegal type/size of operands 714: } 715: bRetry = TRUE; 716: goto RETRY; 717: 718: } 719: ptbRet.pptb1 = table1; 720: goto RETURN_IT; 721: } 722: case 2: 723: { //printf("opflags1 = "); asm_output_flags(opflags1); printf(" "); 724: //printf("opflags2 = "); asm_output_flags(opflags2); printf("\n"); 725: PTRNTAB2 *table2; 726: for (table2 = pop->ptb.pptb2; 727: table2->usOpcode != ASM_END; 728: table2++) 729: { 730: //printf("table1 = "); asm_output_flags(table2->usOp1); printf(" "); 731: //printf("table2 = "); asm_output_flags(table2->usOp2); printf("\n"); 732: if (I64 && (table2->usFlags & _i64_bit)) 733: asmerr( EM_invalid_64bit_opcode, asm_opstr(pop)); 734: 735: bMatch1 = asm_match_flags(opflags1, table2->usOp1); 736: bMatch2 = asm_match_flags(opflags2, table2->usOp2); 737: //printf("match1 = %d, match2 = %d\n",bMatch1,bMatch2); 738: if (bMatch1 && bMatch2) { 739: 740: //printf("match\n"); 741: 742: /* If they both match and the first op in the table is not AL 743: * or size of 8 and the second is immediate 8, 744: * then check to see if the constant 745: * is a signed 8 bit constant. If so, then do not match, otherwise match 746: */ 747: if (!bRetry && 748: !((ASM_GET_uSizemask(table2->usOp1) & _8) || 749: (ASM_GET_uRegmask(table2->usOp1) & _al)) && 750: (ASM_GET_aopty(table2->usOp2) == _imm) && 751: (ASM_GET_uSizemask(table2->usOp2) & _8)) 752: { 753: 754: if (popnd2->disp <= SCHAR_MAX) 755: break; 756: else 757: bFake = TRUE; 758: } 759: else 760: break; 761: } 762: if (asmstate.ucItype == ITopt || 763: asmstate.ucItype == ITfloat) 764: { 765: switch (usNumops) 766: { 767: case 0: 768: if (!table2->usOp1) 769: goto Lfound2; 770: break; 771: case 1: 772: if (bMatch1 && !table2->usOp2) 773: goto Lfound2; 774: break; 775: case 2: 776: break; 777: default: 778: goto PARAM_ERROR; 779: } 780: } 781: #if 0 782: if (asmstate.ucItype == ITshift && 783: !table2->usOp2 && 784: bMatch1 && popnd2->disp == 1 && 785: asm_match_flags(opflags2, 786: CONSTRUCT_FLAGS(_8|_16|_32, _imm,_normal,0)) 787: ) 788: break; 789: #endif 790: } 791: Lfound2: 792: if (table2->usOpcode == ASM_END) 793: { 794: #ifdef DEBUG 795: if (debuga) 796: { printf("\t%s\t", asm_opstr(pop)); 797: if (popnd1) 798: asm_output_popnd(popnd1); 799: if (popnd2) { 800: printf(","); 801: asm_output_popnd(popnd2); 802: } 803: if (popnd3) { 804: printf(","); 805: asm_output_popnd(popnd3); 806: } 807: printf("\n"); 808: 809: printf("OPCODE mismatch = "); 810: if (popnd1) 811: asm_output_flags(popnd1->usFlags); 812: else 813: printf("NONE"); 814: printf( " Op2 = "); 815: if (popnd2) 816: asm_output_flags(popnd2->usFlags); 817: else 818: printf("NONE"); 819: printf("\n"); 820: } 821: #endif 822: goto TYPE_SIZE_ERROR; 823: } 824: ptbRet.pptb2 = table2; 825: goto RETURN_IT; 826: } 827: case 3: 828: { 829: PTRNTAB3 *table3; 830: for (table3 = pop->ptb.pptb3; 831: table3->usOpcode != ASM_END; 832: table3++) 833: { 834: bMatch1 = asm_match_flags(opflags1, table3->usOp1); 835: bMatch2 = asm_match_flags(opflags2, table3->usOp2); 836: bMatch3 = asm_match_flags(opflags3, table3->usOp3); 837: if (bMatch1 && bMatch2 && bMatch3) 838: goto Lfound3; 839: if (asmstate.ucItype == ITopt) 840: { 841: switch (usNumops) 842: { 843: case 0: 844: if (!table3->usOp1) 845: goto Lfound3; 846: break; 847: case 1: 848: if (bMatch1 && !table3->usOp2) 849: goto Lfound3; 850: break; 851: case 2: 852: if (bMatch1 && bMatch2 && !table3->usOp3) 853: goto Lfound3; 854: break; 855: case 3: 856: break; 857: default: 858: goto PARAM_ERROR; 859: } 860: } 861: } 862: Lfound3: 863: if (table3->usOpcode == ASM_END) 864: { 865: #ifdef DEBUG 866: if (debuga) 867: { printf("\t%s\t", asm_opstr(pop)); 868: if (popnd1) 869: asm_output_popnd(popnd1); 870: if (popnd2) { 871: printf(","); 872: asm_output_popnd(popnd2); 873: } 874: if (popnd3) { 875: printf(","); 876: asm_output_popnd(popnd3); 877: } 878: printf("\n"); 879: 880: printf("OPCODE mismatch = "); 881: if (popnd1) 882: asm_output_flags(popnd1->usFlags); 883: else 884: printf("NONE"); 885: printf( " Op2 = "); 886: if (popnd2) 887: asm_output_flags(popnd2->usFlags); 888: else 889: printf("NONE"); 890: if (popnd3) 891: asm_output_flags(popnd3->usFlags); 892: printf("\n"); 893: } 894: #endif 895: goto TYPE_SIZE_ERROR; 896: } 897: ptbRet.pptb3 = table3; 898: goto RETURN_IT; 899: } 900: } 901: RETURN_IT: 902: if (bRetry && !bFake) 903: { 904: asmerr(EM_bad_op, asm_opstr(pop)); 905: } 906: return ptbRet; 907: } 908: 909: /******************************* 910: */ 911: 912: STATIC opflag_t asm_determine_float_flags(OPND *popnd) 913: { 914: //printf("asm_determine_float_flags()\n"); 915: 916: opflag_t us, usFloat; 917: 918: // Insure that if it is a register, that it is not a normal processor 919: // register. 920: 921: if (popnd->base && 922: !popnd->s && !popnd->disp && !popnd->real 923: && !(popnd->base->ty & (_r8 | _r16 | _r32))) 924: { 925: return popnd->base->ty; 926: } 927: if (popnd->pregDisp1 && !popnd->base) 928: { 929: us = asm_float_type_size(popnd->ptype, &usFloat); 930: //printf("us = x%x, usFloat = x%x\n", us, usFloat); 931: if (popnd->pregDisp1->ty & (_r32 | _r64)) 932: return(CONSTRUCT_FLAGS(us, _m, _addr32, usFloat)); 933: else 934: if (popnd->pregDisp1->ty & _r16) 935: return(CONSTRUCT_FLAGS(us, _m, _addr16, usFloat)); 936: } 937: else if (popnd->s != 0) 938: { 939: us = asm_float_type_size(popnd->ptype, &usFloat); 940: return CONSTRUCT_FLAGS(us, _m, _normal, usFloat); 941: } 942: 943: if (popnd->segreg) 944: { 945: us = asm_float_type_size(popnd->ptype, &usFloat); 946: if (I16) 947: return(CONSTRUCT_FLAGS(us, _m, _addr16, usFloat)); 948: else 949: return(CONSTRUCT_FLAGS(us, _m, _addr32, usFloat)); 950: } 951: 952: #if 0 953: if (popnd->real) 954: { 955: switch (popnd->ptype->ty) 956: { 957: case Tfloat32: 958: popnd->s = fconst(popnd->real); 959: return(CONSTRUCT_FLAGS(_32, _m, _normal, 0)); 960: 961: case Tfloat64: 962: popnd->s = dconst(popnd->real); 963: return(CONSTRUCT_FLAGS(0, _m, _normal, _f64)); 964: 965: case Tfloat80: 966: popnd->s = ldconst(popnd->real); 967: return(CONSTRUCT_FLAGS(0, _m, _normal, _f80)); 968: } 969: } 970: #endif 971: 972: asmerr(EM_bad_float_op); // unknown operand for floating point instruction 973: return 0; 974: } 975: 976: /******************************* 977: */ 978: 979: STATIC opflag_t asm_determine_operand_flags(OPND *popnd) 980: { 981: Dsymbol *ps; 982: int ty; 983: opflag_t us; 984: opflag_t sz; 985: ASM_OPERAND_TYPE opty; 986: ASM_MODIFIERS amod; 987: 988: // If specified 'offset' or 'segment' but no symbol 989: if ((popnd->bOffset || popnd->bSeg) && !popnd->s) 990: asmerr(EM_bad_addr_mode); // illegal addressing mode 991: 992: if (asmstate.ucItype == ITfloat) 993: return asm_determine_float_flags(popnd); 994: 995: // If just a register 996: if (popnd->base && !popnd->s && !popnd->disp && !popnd->real) 997: return popnd->base->ty; 998: #if DEBUG 999: if (debuga) 1000: printf("popnd->base = %s\n, popnd->pregDisp1 = %p\n", popnd->base ? popnd->base->regstr : "NONE", popnd->pregDisp1); 1001: #endif 1002: ps = popnd->s; 1003: Declaration *ds = ps ? ps->isDeclaration() : NULL; 1004: if (ds && ds->storage_class & STClazy) 1005: sz = _anysize; 1006: else 1007: sz = asm_type_size((ds && ds->storage_class & (STCout | STCref)) ? popnd->ptype->pointerTo() : popnd->ptype); 1008: if (popnd->pregDisp1 && !popnd->base) 1009: { 1010: if (ps && ps->isLabel() && sz == _anysize) 1011: sz = I16 ? _16 : _32; 1012: return (popnd->pregDisp1->ty & (_r32 | _r64)) 1013: ? CONSTRUCT_FLAGS(sz, _m, _addr32, 0) 1014: : CONSTRUCT_FLAGS(sz, _m, _addr16, 0); 1015: } 1016: else if (ps) 1017: { 1018: if (popnd->bOffset || popnd->bSeg || ps == asmstate.psLocalsize) 1019: return I16 1020: ? CONSTRUCT_FLAGS(_16, _imm, _normal, 0) 1021: : CONSTRUCT_FLAGS(_32, _imm, _normal, 0); 1022: 1023: if (ps->isLabel()) 1024: { 1025: switch (popnd->ajt) 1026: { 1027: case ASM_JUMPTYPE_UNSPECIFIED: 1028: if (ps == asmstate.psDollar) 1029: { 1030: if (popnd->disp >= CHAR_MIN && 1031: popnd->disp <= CHAR_MAX) 1032: us = CONSTRUCT_FLAGS(_8, _rel, _flbl,0); 1033: else 1034: if (popnd->disp >= SHRT_MIN && 1035: popnd->disp <= SHRT_MAX && !I64) 1036: us = CONSTRUCT_FLAGS(_16, _rel, _flbl,0); 1037: else 1038: us = CONSTRUCT_FLAGS(_32, _rel, _flbl,0); 1039: } 1040: else if (asmstate.ucItype != ITjump) 1041: { if (sz == _8) 1042: { us = CONSTRUCT_FLAGS(_8,_rel,_flbl,0); 1043: break; 1044: } 1045: goto case_near; 1046: } 1047: else 1048: us = I16 1049: ? CONSTRUCT_FLAGS(_8|_16, _rel, _flbl,0) 1050: : CONSTRUCT_FLAGS(_8|_32, _rel, _flbl,0); 1051: break; 1052: 1053: case ASM_JUMPTYPE_NEAR: 1054: case_near: 1055: us = I16 1056: ? CONSTRUCT_FLAGS(_16, _rel, _flbl, 0) 1057: : CONSTRUCT_FLAGS(_32, _rel, _flbl, 0); 1058: break; 1059: case ASM_JUMPTYPE_SHORT: 1060: us = CONSTRUCT_FLAGS(_8, _rel, _flbl, 0); 1061: break; 1062: case ASM_JUMPTYPE_FAR: 1063: us = I16 1064: ? CONSTRUCT_FLAGS(_32, _rel, _flbl, 0) 1065: : CONSTRUCT_FLAGS(_48, _rel, _flbl, 0); 1066: break; 1067: default: 1068: assert(0); 1069: } 1070: return us; 1071: } 1072: if (!popnd->ptype) 1073: return CONSTRUCT_FLAGS(sz, _m, _normal, 0); 1074: ty = popnd->ptype->ty; 1075: if (ty == Tpointer && popnd->ptype->nextOf()->ty == Tfunction && 1076: !ps->isVarDeclaration()) 1077: { 1078: #if 1 1079: return CONSTRUCT_FLAGS(_32, _m, _fn16, 0); 1080: #else 1081: ty = popnd->ptype->Tnext->Tty; 1082: if (tyfarfunc(tybasic(ty))) { 1083: return I32 1084: ? CONSTRUCT_FLAGS(_48, _mnoi, _fn32, 0) 1085: : CONSTRUCT_FLAGS(_32, _mnoi, _fn32, 0); 1086: } 1087: else { 1088: return I32 1089: ? CONSTRUCT_FLAGS(_32, _m, _fn16, 0) 1090: : CONSTRUCT_FLAGS(_16, _m, _fn16, 0); 1091: } 1092: #endif 1093: } 1094: else if (ty == Tfunction) 1095: { 1096: #if 1 1097: return CONSTRUCT_FLAGS(_32, _rel, _fn16, 0); 1098: #else 1099: if (tyfarfunc(tybasic(ty))) 1100: return I32 1101: ? CONSTRUCT_FLAGS(_48, _p, _fn32, 0) 1102: : CONSTRUCT_FLAGS(_32, _p, _fn32, 0); 1103: else 1104: return I32 1105: ? CONSTRUCT_FLAGS(_32, _rel, _fn16, 0) 1106: : CONSTRUCT_FLAGS(_16, _rel, _fn16, 0); 1107: #endif 1108: } 1109: else if (asmstate.ucItype == ITjump) 1110: { amod = _normal; 1111: goto L1; 1112: } 1113: else 1114: return CONSTRUCT_FLAGS(sz, _m, _normal, 0); 1115: } 1116: if (popnd->segreg /*|| popnd->bPtr*/) 1117: { 1118: amod = I16 ? _addr16 : _addr32; 1119: if (asmstate.ucItype == ITjump) 1120: { 1121: L1: 1122: opty = _m; 1123: if (I16) 1124: { if (sz == _32) 1125: opty = _mnoi; 1126: } 1127: else 1128: { if (sz == _48) 1129: opty = _mnoi; 1130: } 1131: us = CONSTRUCT_FLAGS(sz,opty,amod,0); 1132: } 1133: else 1134: us = CONSTRUCT_FLAGS(sz, 1135: // _rel, amod, 0); 1136: _m, amod, 0); 1137: } 1138: 1139: else if (popnd->ptype) 1140: us = CONSTRUCT_FLAGS(sz, _imm, _normal, 0); 1141: 1142: else if (popnd->disp >= CHAR_MIN && popnd->disp <= UCHAR_MAX) 1143: us = CONSTRUCT_FLAGS( _8 | _16 | _32 | _64, _imm, _normal, 0); 1144: else if (popnd->disp >= SHRT_MIN && popnd->disp <= USHRT_MAX) 1145: us = CONSTRUCT_FLAGS( _16 | _32 | _64, _imm, _normal, 0); 1146: else if (popnd->disp >= INT_MIN && popnd->disp <= UINT_MAX) 1147: us = CONSTRUCT_FLAGS( _32 | _64, _imm, _normal, 0); 1148: else 1149: us = CONSTRUCT_FLAGS( _64, _imm, _normal, 0); 1150: return us; 1151: } 1152: 1153: /****************************** 1154: * Convert assembly instruction into a code, and append 1155: * it to the code generated for this block. 1156: */ 1157: 1158: STATIC code *asm_emit(Loc loc, 1159: unsigned usNumops, PTRNTAB ptb, 1160: OP *pop, 1161: OPND *popnd1, OPND *popnd2, OPND *popnd3) 1162: { 1163: #ifdef DEBUG 1164: unsigned char auchOpcode[16]; 1165: unsigned usIdx = 0; 1166: #define emit(op) (auchOpcode[usIdx++] = op) 1167: #else 1168: #define emit(op) ((void)(op)) 1169: #endif 1170: Identifier *id; 1171: // unsigned us; 1172: unsigned char *puc; 1173: unsigned usDefaultseg; 1174: code *pc = NULL; 1175: OPND *popndTmp; 1176: ASM_OPERAND_TYPE aoptyTmp; 1177: unsigned uSizemaskTmp; 1178: REG *pregSegment; 1179: code *pcPrefix = NULL; 1180: //ASM_OPERAND_TYPE aopty1 = _reg , aopty2 = 0, aopty3 = 0; 1181: ASM_MODIFIERS amod1 = _normal, amod2 = _normal; 1182: unsigned uSizemaskTable1 =0, uSizemaskTable2 =0, 1183: uSizemaskTable3 =0; 1184: ASM_OPERAND_TYPE aoptyTable1 = _reg, aoptyTable2 = _reg, aoptyTable3 = _reg; 1185: ASM_MODIFIERS amodTable1 = _normal, 1186: amodTable2 = _normal; 1187: unsigned uRegmaskTable1 = 0, uRegmaskTable2 =0; 1188: 1189: pc = code_calloc(); 1190: pc->Iflags |= CFpsw; // assume we want to keep the flags 1191: if (popnd1) 1192: { 1193: //aopty1 = ASM_GET_aopty(popnd1->usFlags); 1194: amod1 = ASM_GET_amod(popnd1->usFlags); 1195: 1196: uSizemaskTable1 = ASM_GET_uSizemask(ptb.pptb1->usOp1); 1197: aoptyTable1 = ASM_GET_aopty(ptb.pptb1->usOp1); 1198: amodTable1 = ASM_GET_amod(ptb.pptb1->usOp1); 1199: uRegmaskTable1 = ASM_GET_uRegmask(ptb.pptb1->usOp1); 1200: 1201: } 1202: if (popnd2) 1203: { 1204: #if 0 1205: printf("\nasm_emit:\nop: "); 1206: asm_output_flags(popnd2->usFlags); 1207: printf("\ntb: "); 1208: asm_output_flags(ptb.pptb2->usOp2); 1209: printf("\n"); 1210: #endif 1211: //aopty2 = ASM_GET_aopty(popnd2->usFlags); 1212: amod2 = ASM_GET_amod(popnd2->usFlags); 1213: 1214: uSizemaskTable2 = ASM_GET_uSizemask(ptb.pptb2->usOp2); 1215: aoptyTable2 = ASM_GET_aopty(ptb.pptb2->usOp2); 1216: amodTable2 = ASM_GET_amod(ptb.pptb2->usOp2); 1217: uRegmaskTable2 = ASM_GET_uRegmask(ptb.pptb2->usOp2); 1218: } 1219: if (popnd3) 1220: { 1221: //aopty3 = ASM_GET_aopty(popnd3->usFlags); 1222: 1223: uSizemaskTable3 = ASM_GET_uSizemask(ptb.pptb3->usOp3); 1224: aoptyTable3 = ASM_GET_aopty(ptb.pptb3->usOp3); 1225: } 1226: 1227: asmstate.statement->regs |= asm_modify_regs(ptb, popnd1, popnd2); 1228: 1229: if (I16 && ptb.pptb0->usFlags & _I386) 1230: { 1231: switch (usNumops) 1232: { 1233: case 0: 1234: break; 1235: case 1: 1236: if (popnd1 && popnd1->s) 1237: { 1238: L386_WARNING: 1239: id = popnd1->s->ident; 1240: L386_WARNING2: 1241: if (config.target_cpu < TARGET_80386) 1242: { // Reference to %s caused a 386 instruction to be generated 1243: //warerr(WM_386_op, id->toChars()); 1244: } 1245: } 1246: break; 1247: case 2: 1248: case 3: // The third operand is always an _imm 1249: if (popnd1 && popnd1->s) 1250: goto L386_WARNING; 1251: if (popnd2 && popnd2->s) 1252: { 1253: id = popnd2->s->ident; 1254: goto L386_WARNING2; 1255: } 1256: break; 1257: } 1258: } 1259: 1260: if (ptb.pptb0->usFlags & _64_bit && !I64) 1261: error(asmstate.loc, "use -m64 to compile 64 bit instructions"); 1262: 1263: if (I64 && (ptb.pptb0->usFlags & _64_bit)) 1264: { 1265: emit(REX | REX_W); 1266: pc->Irex |= REX_W; 1267: } 1268: 1269: switch (usNumops) 1270: { 1271: case 0: 1272: if (((I32 | I64) && (ptb.pptb0->usFlags & _16_bit)) || 1273: (I16 && (ptb.pptb0->usFlags & _32_bit))) 1274: { 1275: emit(0x66); 1276: pc->Iflags |= CFopsize; 1277: } 1278: break; 1279: 1280: // 3 and 2 are the same because the third operand is always 1281: // an immediate and does not affect operation size 1282: case 3: 1283: case 2: 1284: if ((I32 && 1285: (amod2 == _addr16 || 1286: (uSizemaskTable2 & _16 && aoptyTable2 == _rel) || 1287: (uSizemaskTable2 & _32 && aoptyTable2 == _mnoi) || 1288: (ptb.pptb2->usFlags & _16_bit_addr) 1289: ) 1290: ) || 1291: (I16 && 1292: (amod2 == _addr32 || 1293: (uSizemaskTable2 & _32 && aoptyTable2 == _rel) || 1294: (uSizemaskTable2 & _48 && aoptyTable2 == _mnoi) || 1295: (ptb.pptb2->usFlags & _32_bit_addr))) 1296: ) 1297: { 1298: emit(0x67); 1299: pc->Iflags |= CFaddrsize; 1300: if (I32) 1301: amod2 = _addr16; 1302: else 1303: amod2 = _addr32; 1304: popnd2->usFlags &= ~CONSTRUCT_FLAGS(0,0,7,0); 1305: popnd2->usFlags |= CONSTRUCT_FLAGS(0,0,amod2,0); 1306: } 1307: 1308: 1309: /* Fall through, operand 1 controls the opsize, but the 1310: address size can be in either operand 1 or operand 2, 1311: hence the extra checking the flags tested for SHOULD 1312: be mutex on operand 1 and operand 2 because there is 1313: only one MOD R/M byte 1314: */ 1315: 1316: case 1: 1317: if ((I32 && 1318: (amod1 == _addr16 || 1319: (uSizemaskTable1 & _16 && aoptyTable1 == _rel) || 1320: (uSizemaskTable1 & _32 && aoptyTable1 == _mnoi) || 1321: (ptb.pptb1->usFlags & _16_bit_addr))) || 1322: (I16 && 1323: (amod1 == _addr32 || 1324: (uSizemaskTable1 & _32 && aoptyTable1 == _rel) || 1325: (uSizemaskTable1 & _48 && aoptyTable1 == _mnoi) || 1326: (ptb.pptb1->usFlags & _32_bit_addr)))) 1327: { 1328: emit(0x67); // address size prefix 1329: pc->Iflags |= CFaddrsize; 1330: if (I32) 1331: amod1 = _addr16; 1332: else 1333: amod1 = _addr32; 1334: popnd1->usFlags &= ~CONSTRUCT_FLAGS(0,0,7,0); 1335: popnd1->usFlags |= CONSTRUCT_FLAGS(0,0,amod1,0); 1336: } 1337: 1338: // If the size of the operand is unknown, assume that it is 1339: // the default size 1340: if (((I64 || I32) && (ptb.pptb0->usFlags & _16_bit)) || 1341: (I16 && (ptb.pptb0->usFlags & _32_bit))) 1342: { 1343: //if (asmstate.ucItype != ITjump) 1344: { emit(0x66); 1345: pc->Iflags |= CFopsize; 1346: } 1347: } 1348: if (((pregSegment = (popndTmp = popnd1)->segreg) != NULL) || 1349: ((popndTmp = popnd2) != NULL && 1350: (pregSegment = popndTmp->segreg) != NULL) 1351: ) 1352: { 1353: if ((popndTmp->pregDisp1 && 1354: popndTmp->pregDisp1->val == _BP) || 1355: popndTmp->pregDisp2 && 1356: popndTmp->pregDisp2->val == _BP) 1357: usDefaultseg = _SS; 1358: else 1359: usDefaultseg = _DS; 1360: if (pregSegment->val != usDefaultseg) 1361: switch (pregSegment->val) { 1362: case _CS: 1363: emit(0x2e); 1364: pc->Iflags |= CFcs; 1365: break; 1366: case _SS: 1367: emit(0x36); 1368: pc->Iflags |= CFss; 1369: break; 1370: case _DS: 1371: emit(0x3e); 1372: pc->Iflags |= CFds; 1373: break; 1374: case _ES: 1375: emit(0x26); 1376: pc->Iflags |= CFes; 1377: break; 1378: case _FS: 1379: emit(0x64); 1380: pc->Iflags |= CFfs; 1381: break; 1382: case _GS: 1383: emit(0x65); 1384: pc->Iflags |= CFgs; 1385: break; 1386: default: 1387: assert(0); 1388: } 1389: } 1390: break; 1391: } 1392: unsigned usOpcode = ptb.pptb0->usOpcode; 1393: 1394: pc->Iop = usOpcode; 1395: if ((usOpcode & 0xFFFD00) == 0x0F3800) // SSSE3, SSE4 1396: { emit(0xFF); 1397: emit(0xFD); 1398: emit(0x00); 1399: goto L3; 1400: } 1401: switch (usOpcode & 0xFF0000) 1402: { 1403: case 0: 1404: break; 1405: 1406: case 0x660000: 1407: usOpcode &= 0xFFFF; 1408: goto L3; 1409: 1410: case 0xF20000: // REPNE 1411: case 0xF30000: // REP/REPE 1412: // BUG: What if there's an address size prefix or segment 1413: // override prefix? Must the REP be adjacent to the rest 1414: // of the opcode? 1415: usOpcode &= 0xFFFF; 1416: goto L3; 1417: 1418: case 0x0F0000: // an AMD instruction 1419: puc = ((unsigned char *) &usOpcode); 1420: if (puc[1] != 0x0F) // if not AMD instruction 0x0F0F 1421: goto L4; 1422: emit(puc[2]); 1423: emit(puc[1]); 1424: emit(puc[0]); 1425: pc->Iop >>= 8; 1426: pc->IEVint2 = puc[0]; 1427: pc->IFL2 = FLconst; 1428: goto L3; 1429: 1430: default: 1431: puc = ((unsigned char *) &usOpcode); 1432: L4: 1433: emit(puc[2]); 1434: emit(puc[1]); 1435: emit(puc[0]); 1436: pc->Iop >>= 8; 1437: pc->Irm = puc[0]; 1438: goto L3; 1439: } 1440: if (usOpcode & 0xff00) 1441: { 1442: puc = ((unsigned char *) &(usOpcode)); 1443: emit(puc[1]); 1444: emit(puc[0]); 1445: pc->Iop = puc[1]; 1446: if (pc->Iop == 0x0f) 1447: pc->Iop = 0x0F00 | puc[0]; 1448: else 1449: { 1450: if (usOpcode == 0xDFE0) // FSTSW AX 1451: { pc->Irm = puc[0]; 1452: goto L2; 1453: } 1454: if (asmstate.ucItype == ITfloat) 1455: pc->Irm = puc[0]; 1456: else 1457: { pc->IEVint2 = puc[0]; 1458: pc->IFL2 = FLconst; 1459: } 1460: } 1461: } 1462: else 1463: { 1464: emit(usOpcode); 1465: } 1466: L3: ; 1467: 1468: // If CALL, Jxx or LOOPx to a symbolic location 1469: if (/*asmstate.ucItype == ITjump &&*/ 1470: popnd1 && popnd1->s && popnd1->s->isLabel()) 1471: { Dsymbol *s; 1472: 1473: s = popnd1->s; 1474: if (s == asmstate.psDollar) 1475: { 1476: pc->IFL2 = FLconst; 1477: if (uSizemaskTable1 & (_8 | _16)) 1478: pc->IEVint2 = popnd1->disp;
warning C4244: '=' : conversion from 'targ_llong' to 'targ_int', possible loss of data
1479: else if (uSizemaskTable1 & _32) 1480: pc->IEVpointer2 = (targ_size_t) popnd1->disp; 1481: } 1482: else 1483: { LabelDsymbol *label; 1484: 1485: label = s->isLabel(); 1486: if (label) 1487: { if ((pc->Iop & ~0x0F) == 0x70) 1488: pc->Iflags |= CFjmp16; 1489: if (usNumops == 1) 1490: { pc->IFL2 = FLblock; 1491: pc->IEVlsym2 = label; 1492: } 1493: else 1494: { pc->IFL1 = FLblock; 1495: pc->IEVlsym1 = label; 1496: } 1497: } 1498: } 1499: } 1500: 1501: switch (usNumops) 1502: { 1503: case 0: 1504: break; 1505: case 1: 1506: if (((aoptyTable1 == _reg || aoptyTable1 == _float) && 1507: amodTable1 == _normal && (uRegmaskTable1 & _rplus_r))) 1508: { 1509: unsigned reg = popnd1->base->val; 1510: if (reg & 8) 1511: { reg &= 7; 1512: pc->Irex |= REX_B; 1513: assert(I64); 1514: } 1515: if (asmstate.ucItype == ITfloat) 1516: pc->Irm += reg; 1517: else 1518: pc->Iop += reg; 1519: #ifdef DEBUG 1520: auchOpcode[usIdx-1] += reg; 1521: #endif 1522: } 1523: else 1524: { asm_make_modrm_byte( 1525: #ifdef DEBUG 1526: auchOpcode, &usIdx, 1527: #endif 1528: pc, 1529: ptb.pptb1->usFlags, 1530: popnd1, NULL); 1531: } 1532: popndTmp = popnd1; 1533: aoptyTmp = aoptyTable1; 1534: uSizemaskTmp = uSizemaskTable1; 1535: L1: 1536: if (aoptyTmp == _imm) 1537: { 1538: Declaration *d = popndTmp->s ? popndTmp->s->isDeclaration() 1539: : NULL; 1540: if (popndTmp->bSeg) 1541: { 1542: 1543: if (!(d && d->isDataseg())) 1544: asmerr(EM_bad_addr_mode); // illegal addressing mode 1545: } 1546: switch (uSizemaskTmp) 1547: { 1548: case _8: 1549: case _16: 1550: case _32: 1551: case _64: 1552: if (popndTmp->s == asmstate.psLocalsize) 1553: { 1554: pc->IFL2 = FLlocalsize; 1555: pc->IEVdsym2 = NULL; 1556: pc->Iflags |= CFoff; 1557: pc->IEVoffset2 = popndTmp->disp;
warning C4244: '=' : conversion from 'targ_llong' to 'targ_size_t', possible loss of data
1558: } 1559: else if (d) 1560: { 1561: #if 0 1562: if ((pc->IFL2 = d->Sfl) == 0) 1563: #endif 1564: pc->IFL2 = FLdsymbol; 1565: pc->Iflags &= ~(CFseg | CFoff); 1566: if (popndTmp->bSeg) 1567: pc->Iflags |= CFseg; 1568: else 1569: pc->Iflags |= CFoff; 1570: pc->IEVoffset2 = popndTmp->disp;
warning C4244: '=' : conversion from 'targ_llong' to 'targ_size_t', possible loss of data
1571: pc->IEVdsym2 = d; 1572: } 1573: else 1574: { 1575: pc->IEVllong2 = popndTmp->disp; 1576: pc->IFL2 = FLconst; 1577: } 1578: break; 1579: } 1580: } 1581: 1582: break; 1583: case 2: 1584: // 1585: // If there are two immediate operands then 1586: // 1587: if (aoptyTable1 == _imm && 1588: aoptyTable2 == _imm) 1589: { 1590: pc->IEVint1 = popnd1->disp;
warning C4244: '=' : conversion from 'targ_llong' to 'targ_int', possible loss of data
1591: pc->IFL1 = FLconst; 1592: pc->IEVint2 = popnd2->disp;
warning C4244: '=' : conversion from 'targ_llong' to 'targ_int', possible loss of data
1593: pc->IFL2 = FLconst; 1594: break; 1595: } 1596: if (aoptyTable2 == _m || 1597: aoptyTable2 == _rel || 1598: // If not MMX register (_mm) or XMM register (_xmm) 1599: (amodTable1 == _rspecial && !(uRegmaskTable1 & (0x08 | 0x10)) && !uSizemaskTable1) || 1600: aoptyTable2 == _rm || 1601: (popnd1->usFlags == _r32 && popnd2->usFlags == _xmm) || 1602: (popnd1->usFlags == _r32 && popnd2->usFlags == _mm)) 1603: { 1604: #if 0 1605: printf("test4 %d,%d,%d,%d\n", 1606: (aoptyTable2 == _m), 1607: (aoptyTable2 == _rel), 1608: (amodTable1 == _rspecial && !(uRegmaskTable1 & (0x08 | 0x10))), 1609: (aoptyTable2 == _rm) 1610: ); 1611: printf("usOpcode = %x\n", usOpcode); 1612: #endif 1613: if (ptb.pptb0->usOpcode == 0x0F7E || // MOVD _rm32,_mm 1614: ptb.pptb0->usOpcode == 0x660F7E // MOVD _rm32,_xmm 1615: ) 1616: { 1617: asm_make_modrm_byte( 1618: #ifdef DEBUG 1619: auchOpcode, &usIdx, 1620: #endif 1621: pc, 1622: ptb.pptb1->usFlags, 1623: popnd1, popnd2); 1624: } 1625: else 1626: { 1627: asm_make_modrm_byte( 1628: #ifdef DEBUG 1629: auchOpcode, &usIdx, 1630: #endif 1631: pc, 1632: ptb.pptb1->usFlags, 1633: popnd2, popnd1); 1634: } 1635: popndTmp = popnd1; 1636: aoptyTmp = aoptyTable1; 1637: uSizemaskTmp = uSizemaskTable1; 1638: } 1639: else 1640: { 1641: if (((aoptyTable1 == _reg || aoptyTable1 == _float) && 1642: amodTable1 == _normal && 1643: (uRegmaskTable1 & _rplus_r))) 1644: { 1645: unsigned reg = popnd1->base->val; 1646: if (reg & 8) 1647: { reg &= 7; 1648: pc->Irex |= REX_B; 1649: assert(I64); 1650: } 1651: if (asmstate.ucItype == ITfloat) 1652: pc->Irm += reg; 1653: else 1654: pc->Iop += reg; 1655: #ifdef DEBUG 1656: auchOpcode[usIdx-1] += reg; 1657: #endif 1658: } 1659: else 1660: if (((aoptyTable2 == _reg || aoptyTable2 == _float) && 1661: amodTable2 == _normal && 1662: (uRegmaskTable2 & _rplus_r))) 1663: { 1664: unsigned reg = popnd2->base->val; 1665: if (reg & 8) 1666: { reg &= 7; 1667: pc->Irex |= REX_B; 1668: assert(I64); 1669: } 1670: if (asmstate.ucItype == ITfloat) 1671: pc->Irm += reg; 1672: else 1673: pc->Iop += reg; 1674: #ifdef DEBUG 1675: auchOpcode[usIdx-1] += reg; 1676: #endif 1677: } 1678: else if (ptb.pptb0->usOpcode == 0xF30FD6 || 1679: ptb.pptb0->usOpcode == 0x0F12 || 1680: ptb.pptb0->usOpcode == 0x0F16 || 1681: ptb.pptb0->usOpcode == 0x660F50 || 1682: ptb.pptb0->usOpcode == 0x0F50 || 1683: ptb.pptb0->usOpcode == 0x660FD7 || 1684: ptb.pptb0->usOpcode == 0x0FD7) 1685: { 1686: asm_make_modrm_byte( 1687: #ifdef DEBUG 1688: auchOpcode, &usIdx, 1689: #endif 1690: pc, 1691: ptb.pptb1->usFlags, 1692: popnd2, popnd1); 1693: } 1694: else 1695: { 1696: asm_make_modrm_byte( 1697: #ifdef DEBUG 1698: auchOpcode, &usIdx, 1699: #endif 1700: pc, 1701: ptb.pptb1->usFlags, 1702: popnd1, popnd2); 1703: 1704: } 1705: if (aoptyTable1 == _imm) 1706: { 1707: popndTmp = popnd1; 1708: aoptyTmp = aoptyTable1; 1709: uSizemaskTmp = uSizemaskTable1; 1710: } 1711: else 1712: { 1713: popndTmp = popnd2; 1714: aoptyTmp = aoptyTable2; 1715: uSizemaskTmp = uSizemaskTable2; 1716: } 1717: } 1718: goto L1; 1719: 1720: case 3: 1721: if (aoptyTable2 == _m || aoptyTable2 == _rm || 1722: usOpcode == 0x0FC5 || // pextrw _r32, _mm, _imm8 1723: usOpcode == 0x660FC5 || // pextrw _r32, _xmm, _imm8 1724: usOpcode == 0x660F3A20 || // pinsrb _xmm, _r32/m8, _imm8 1725: usOpcode == 0x660F3A22 // pinsrd _xmm, _rm32, _imm8 1726: ) 1727: { 1728: asm_make_modrm_byte( 1729: #ifdef DEBUG 1730: auchOpcode, &usIdx, 1731: #endif 1732: pc, 1733: ptb.pptb1->usFlags, 1734: popnd2, popnd1); 1735: popndTmp = popnd3; 1736: aoptyTmp = aoptyTable3; 1737: uSizemaskTmp = uSizemaskTable3; 1738: } 1739: else { 1740: 1741: if (((aoptyTable1 == _reg || aoptyTable1 == _float) && 1742: amodTable1 == _normal && 1743: (uRegmaskTable1 &_rplus_r))) 1744: { 1745: unsigned reg = popnd1->base->val; 1746: if (reg & 8) 1747: { reg &= 7; 1748: pc->Irex |= REX_B; 1749: assert(I64); 1750: } 1751: if (asmstate.ucItype == ITfloat) 1752: pc->Irm += reg; 1753: else 1754: pc->Iop += reg; 1755: #ifdef DEBUG 1756: auchOpcode[usIdx-1] += reg; 1757: #endif 1758: } 1759: else 1760: if (((aoptyTable2 == _reg || aoptyTable2 == _float) && 1761: amodTable2 == _normal && 1762: (uRegmaskTable2 &_rplus_r))) 1763: { 1764: unsigned reg = popnd1->base->val; 1765: if (reg & 8) 1766: { reg &= 7; 1767: pc->Irex |= REX_B; 1768: assert(I64); 1769: } 1770: if (asmstate.ucItype == ITfloat) 1771: pc->Irm += reg; 1772: else 1773: pc->Iop += reg; 1774: #ifdef DEBUG 1775: auchOpcode[usIdx-1] += reg; 1776: #endif 1777: } 1778: else 1779: asm_make_modrm_byte( 1780: #ifdef DEBUG 1781: auchOpcode, &usIdx, 1782: #endif 1783: pc, 1784: ptb.pptb1->usFlags, 1785: popnd1, popnd2); 1786: 1787: popndTmp = popnd3; 1788: aoptyTmp = aoptyTable3; 1789: uSizemaskTmp = uSizemaskTable3; 1790: 1791: } 1792: goto L1; 1793: } 1794: L2: 1795: 1796: if ((pc->Iop & ~7) == 0xD8 && 1797: ADDFWAIT() && 1798: !(ptb.pptb0->usFlags & _nfwait)) 1799: pc->Iflags |= CFwait; 1800: else if ((ptb.pptb0->usFlags & _fwait) && 1801: config.target_cpu >= TARGET_80386) 1802: pc->Iflags |= CFwait; 1803: 1804: #ifdef DEBUG 1805: if (debuga) 1806: { unsigned u; 1807: 1808: for (u = 0; u < usIdx; u++) 1809: printf(" %02X", auchOpcode[u]); 1810: 1811: printf("\t%s\t", asm_opstr(pop)); 1812: if (popnd1) 1813: asm_output_popnd(popnd1); 1814: if (popnd2) { 1815: printf(","); 1816: asm_output_popnd(popnd2); 1817: } 1818: if (popnd3) { 1819: printf(","); 1820: asm_output_popnd(popnd3); 1821: } 1822: printf("\n"); 1823: } 1824: #endif 1825: pc = cat(pcPrefix, pc); 1826: pc = asm_genloc(loc, pc); 1827: return pc; 1828: } 1829: 1830: /******************************* 1831: * Prepend line number to c. 1832: */ 1833: 1834: code *asm_genloc(Loc loc, code *c) 1835: { 1836: if (global.params.symdebug) 1837: { code *pcLin; 1838: Srcpos srcpos; 1839: 1840: memset(&srcpos, 0, sizeof(srcpos)); 1841: srcpos.Slinnum = loc.linnum; 1842: srcpos.Sfilename = (char *)loc.filename; 1843: pcLin = genlinnum(NULL, srcpos); 1844: c = cat(pcLin, c); 1845: } 1846: return c; 1847: } 1848: 1849: 1850: /******************************* 1851: */ 1852: 1853: STATIC void asmerr(int errnum, ...) 1854: { const char *format; 1855: 1856: const char *p = asmstate.loc.toChars(); 1857: if (*p) 1858: printf("%s: ", p); 1859: 1860: format = asmerrmsgs[errnum]; 1861: va_list ap; 1862: va_start(ap, errnum); 1863: vprintf(format, ap); 1864: va_end(ap); 1865: 1866: printf("\n"); 1867: fflush(stdout); 1868: longjmp(asmstate.env,1); 1869: } 1870: 1871: /******************************* 1872: */ 1873: 1874: STATIC void asmerr(const char *format, ...) 1875: { 1876: const char *p = asmstate.loc.toChars(); 1877: if (*p) 1878: printf("%s: ", p); 1879: 1880: va_list ap; 1881: va_start(ap, format); 1882: vprintf(format, ap); 1883: va_end(ap); 1884: 1885: printf("\n"); 1886: fflush(stdout); 1887: 1888: longjmp(asmstate.env,1); 1889: } 1890: 1891: /******************************* 1892: */ 1893: 1894: STATIC opflag_t asm_float_type_size(Type *ptype, opflag_t *pusFloat) 1895: { 1896: *pusFloat = 0; 1897: 1898: //printf("asm_float_type_size('%s')\n", ptype->toChars()); 1899: if (ptype && ptype->isscalar()) 1900: { 1901: int sz = (int)ptype->size(); 1902: if (sz == REALSIZE) 1903: { *pusFloat = _f80; 1904: return 0; 1905: } 1906: switch (sz) 1907: { 1908: case 2: 1909: return _16; 1910: case 4: 1911: return _32; 1912: case 8: 1913: *pusFloat = _f64; 1914: return 0; 1915: case 10: 1916: *pusFloat = _f80; 1917: return 0; 1918: default: 1919: break; 1920: } 1921: } 1922: *pusFloat = _fanysize; 1923: return _anysize; 1924: } 1925: 1926: /******************************* 1927: */ 1928: 1929: STATIC int asm_isint(OPND *o) 1930: { 1931: if (!o || o->base || o->s) 1932: return 0; 1933: //return o->disp != 0; 1934: return 1; 1935: } 1936: 1937: STATIC int asm_isNonZeroInt(OPND *o) 1938: { 1939: if (!o || o->base || o->s) 1940: return 0; 1941: return o->disp != 0; 1942: } 1943: 1944: /******************************* 1945: */ 1946: 1947: STATIC int asm_is_fpreg(char *szReg) 1948: { 1949: #if 1 1950: return(szReg[2] == '\0' && szReg[0] == 'S' && 1951: szReg[1] == 'T'); 1952: #else 1953: return(szReg[2] == '\0' && (szReg[0] == 's' || szReg[0] == 'S') && 1954: (szReg[1] == 't' || szReg[1] == 'T')); 1955: #endif 1956: } 1957: 1958: /******************************* 1959: * Merge operands o1 and o2 into a single operand. 1960: */ 1961: 1962: STATIC OPND *asm_merge_opnds(OPND *o1, OPND *o2) 1963: { 1964: #ifdef DEBUG 1965: const char *psz; 1966: #endif 1967: #ifdef DEBUG 1968: if (debuga) 1969: { printf("asm_merge_opnds(o1 = "); 1970: if (o1) asm_output_popnd(o1); 1971: printf(", o2 = "); 1972: if (o2) asm_output_popnd(o2); 1973: printf(")\n"); 1974: } 1975: #endif 1976: if (!o1) 1977: return o2; 1978: if (!o2) 1979: return o1; 1980: #ifdef EXTRA_DEBUG 1981: printf("Combining Operands: mult1 = %d, mult2 = %d", 1982: o1->uchMultiplier, o2->uchMultiplier); 1983: #endif 1984: /* combine the OPND's disp field */ 1985: if (o2->segreg) { 1986: if (o1->segreg) { 1987: #ifdef DEBUG 1988: psz = "o1->segment && o2->segreg"; 1989: #endif 1990: goto ILLEGAL_ADDRESS_ERROR; 1991: } 1992: else 1993: o1->segreg = o2->segreg; 1994: } 1995: 1996: // combine the OPND's symbol field 1997: if (o1->s && o2->s) 1998: { 1999: #ifdef DEBUG 2000: psz = "o1->s && os->s"; 2001: #endif 2002: ILLEGAL_ADDRESS_ERROR: 2003: #ifdef DEBUG 2004: printf("Invalid addr because /%s/\n", psz); 2005: #endif 2006: 2007: asmerr(EM_bad_addr_mode); // illegal addressing mode 2008: } 2009: else if (o2->s) 2010: o1->s = o2->s; 2011: else if (o1->s && o1->s->isTupleDeclaration()) 2012: { TupleDeclaration *tup = o1->s->isTupleDeclaration(); 2013: 2014: size_t index = o2->disp;
warning C4244: 'initializing' : conversion from 'targ_llong' to 'size_t', possible loss of data
2015: if (index >= tup->objects->dim) 2016: error(asmstate.loc, "tuple index %u exceeds length %u", index, tup->objects->dim); 2017: else 2018: { 2019: Object *o = tup->objects->tdata()[index]; 2020: if (o->dyncast() == DYNCAST_DSYMBOL) 2021: { o1->s = (Dsymbol *)o; 2022: return o1; 2023: } 2024: else if (o->dyncast() == DYNCAST_EXPRESSION) 2025: { Expression *e = (Expression *)o; 2026: if (e->op == TOKvar) 2027: { o1->s = ((VarExp *)e)->var; 2028: return o1; 2029: } 2030: else if (e->op == TOKfunction) 2031: { o1->s = ((FuncExp *)e)->fd; 2032: return o1; 2033: } 2034: } 2035: error(asmstate.loc, "invalid asm operand %s", o1->s->toChars()); 2036: } 2037: } 2038: 2039: if (o1->disp && o2->disp) 2040: o1->disp += o2->disp; 2041: else if (o2->disp) 2042: o1->disp = o2->disp; 2043: 2044: /* combine the OPND's base field */ 2045: if (o1->base != NULL && o2->base != NULL) { 2046: #ifdef DEBUG 2047: psz = "o1->base != NULL && o2->base != NULL"; 2048: #endif 2049: goto ILLEGAL_ADDRESS_ERROR; 2050: } 2051: else if (o2->base) 2052: o1->base = o2->base; 2053: 2054: /* Combine the displacement register fields */ 2055: if (o2->pregDisp1) 2056: { 2057: if (o1->pregDisp2) 2058: { 2059: #ifdef DEBUG 2060: psz = "o2->pregDisp1 && o1->pregDisp2"; 2061: #endif 2062: goto ILLEGAL_ADDRESS_ERROR; 2063: } 2064: else if (o1->pregDisp1) 2065: { 2066: if (o1->uchMultiplier || 2067: (o2->pregDisp1->val == _ESP && 2068: (o2->pregDisp1->ty & _r32) && 2069: !o2->uchMultiplier)) 2070: { 2071: o1->pregDisp2 = o1->pregDisp1; 2072: o1->pregDisp1 = o2->pregDisp1; 2073: } 2074: else 2075: o1->pregDisp2 = o2->pregDisp1; 2076: } 2077: else 2078: o1->pregDisp1 = o2->pregDisp1; 2079: } 2080: if (o2->pregDisp2) { 2081: if (o1->pregDisp2) { 2082: #ifdef DEBUG 2083: psz = "o1->pregDisp2 && o2->pregDisp2"; 2084: #endif 2085: goto ILLEGAL_ADDRESS_ERROR; 2086: } 2087: else 2088: o1->pregDisp2 = o2->pregDisp2; 2089: } 2090: if (o2->uchMultiplier) 2091: { 2092: if (o1->uchMultiplier) 2093: { 2094: #ifdef DEBUG 2095: psz = "o1->uchMultiplier && o2->uchMultiplier"; 2096: #endif 2097: goto ILLEGAL_ADDRESS_ERROR; 2098: } 2099: else 2100: o1->uchMultiplier = o2->uchMultiplier; 2101: } 2102: if (o2->ptype && !o1->ptype) 2103: o1->ptype = o2->ptype; 2104: if (o2->bOffset) 2105: o1->bOffset = o2->bOffset; 2106: if (o2->bSeg) 2107: o1->bSeg = o2->bSeg; 2108: 2109: if (o2->ajt && !o1->ajt) 2110: o1->ajt = o2->ajt; 2111: 2112: opnd_free(o2); 2113: #ifdef EXTRA_DEBUG 2114: printf("Result = %d\n", 2115: o1->uchMultiplier); 2116: #endif 2117: #ifdef DEBUG 2118: if (debuga) 2119: { printf("Merged result = /"); 2120: asm_output_popnd(o1); 2121: printf("/\n"); 2122: } 2123: #endif 2124: return o1; 2125: } 2126: 2127: /*************************************** 2128: */ 2129: 2130: STATIC void asm_merge_symbol(OPND *o1, Dsymbol *s) 2131: { Type *ptype;
warning C4101: 'ptype' : unreferenced local variable
2132: VarDeclaration *v; 2133: EnumMember *em; 2134: 2135: //printf("asm_merge_symbol(s = %s %s)\n", s->kind(), s->toChars()); 2136: s = s->toAlias(); 2137: //printf("s = %s %s\n", s->kind(), s->toChars()); 2138: if (s->isLabel()) 2139: { 2140: o1->s = s; 2141: return; 2142: } 2143: 2144: v = s->isVarDeclaration(); 2145: if (v) 2146: { 2147: if (v->isParameter()) 2148: asmstate.statement->refparam = TRUE; 2149: 2150: v->checkNestedReference(asmstate.sc, asmstate.loc); 2151: #if 0 2152: if (!v->isDataseg() && v->parent != asmstate.sc->parent && v->parent) 2153: { 2154: asmerr(EM_uplevel, v->toChars()); 2155: } 2156: #endif 2157: if (v->storage_class & STCfield) 2158: { 2159: o1->disp += v->offset; 2160: goto L2; 2161: } 2162: if ((v->isConst() 2163: #if DMDV2 2164: || v->isImmutable() || v->storage_class & STCmanifest 2165: #endif 2166: ) && !v->type->isfloating() && v->init) 2167: { ExpInitializer *ei = v->init->isExpInitializer(); 2168: 2169: if (ei) 2170: { 2171: o1->disp = ei->exp->toInteger(); 2172: return; 2173: } 2174: } 2175: } 2176: em = s->isEnumMember(); 2177: if (em) 2178: { 2179: o1->disp = em->value->toInteger(); 2180: return; 2181: } 2182: o1->s = s; // a C identifier 2183: L2: 2184: Declaration *d = s->isDeclaration(); 2185: if (!d) 2186: { 2187: asmerr("%s %s is not a declaration", s->kind(), s->toChars()); 2188: } 2189: else if (d->getType()) 2190: asmerr(EM_type_as_operand, d->getType()->toChars()); 2191: else if (d->isTupleDeclaration()) 2192: ; 2193: else 2194: o1->ptype = d->type->toBasetype(); 2195: } 2196: 2197: /**************************** 2198: * Fill in the modregrm and sib bytes of code. 2199: */ 2200: 2201: STATIC void asm_make_modrm_byte( 2202: #ifdef DEBUG 2203: unsigned char *puchOpcode, unsigned *pusIdx, 2204: #endif 2205: code *pc, 2206: unsigned usFlags, 2207: OPND *popnd, OPND *popnd2) 2208: { 2209: #undef modregrm 2210: 2211: typedef union { 2212: unsigned char uchOpcode; 2213: struct { 2214: unsigned rm : 3; 2215: unsigned reg : 3; 2216: unsigned mod : 2; 2217: } modregrm; 2218: } MODRM_BYTE; // mrmb 2219: 2220: typedef union { 2221: unsigned char uchOpcode; 2222: struct { 2223: unsigned base : 3; 2224: unsigned index : 3; 2225: unsigned ss : 2; 2226: } sib; 2227: } SIB_BYTE; 2228: 2229: 2230: MODRM_BYTE mrmb = { 0 }; 2231: SIB_BYTE sib = { 0 }; 2232: char bSib = FALSE; 2233: char bDisp = FALSE; 2234: unsigned char *puc;
warning C4101: 'puc' : unreferenced local variable
2235: char bModset = FALSE; 2236: Dsymbol *s; 2237: 2238: unsigned uSizemask =0; 2239: ASM_OPERAND_TYPE aopty; 2240: ASM_MODIFIERS amod; 2241: unsigned char bOffsetsym = FALSE; 2242: 2243: #if 0 2244: printf("asm_make_modrm_byte(usFlags = x%x)\n", usFlags); 2245: printf("op1: "); 2246: asm_output_flags(popnd->usFlags); 2247: if (popnd2) 2248: { printf(" op2: "); 2249: asm_output_flags(popnd2->usFlags); 2250: } 2251: printf("\n"); 2252: #endif 2253: 2254: uSizemask = ASM_GET_uSizemask(popnd->usFlags); 2255: aopty = ASM_GET_aopty(popnd->usFlags); 2256: amod = ASM_GET_amod(popnd->usFlags); 2257: s = popnd->s; 2258: if (s) 2259: { 2260: Declaration *d = s->isDeclaration(); 2261: 2262: if (amod == _fn16 && aopty == _rel && popnd2) 2263: { aopty = _m; 2264: goto L1; 2265: } 2266: 2267: if (amod == _fn16 || amod == _fn32) 2268: { 2269: pc->Iflags |= CFoff; 2270: #ifdef DEBUG 2271: puchOpcode[(*pusIdx)++] = 0; 2272: puchOpcode[(*pusIdx)++] = 0; 2273: #endif 2274: if (aopty == _m || aopty == _mnoi) 2275: { 2276: pc->IFL1 = FLdata; 2277: pc->IEVdsym1 = d; 2278: pc->IEVoffset1 = 0; 2279: } 2280: else 2281: { 2282: if (aopty == _p) 2283: pc->Iflags |= CFseg; 2284: #ifdef DEBUG 2285: if (aopty == _p || aopty == _rel) 2286: { puchOpcode[(*pusIdx)++] = 0; 2287: puchOpcode[(*pusIdx)++] = 0; 2288: } 2289: #endif 2290: pc->IFL2 = FLfunc; 2291: pc->IEVdsym2 = d; 2292: pc->IEVoffset2 = 0; 2293: //return; 2294: } 2295: } 2296: else 2297: { 2298: L1: 2299: LabelDsymbol *label = s->isLabel(); 2300: if (label) 2301: { 2302: if (s == asmstate.psDollar) 2303: { 2304: pc->IFL1 = FLconst; 2305: if (uSizemask & (_8 | _16)) 2306: pc->IEVint1 = popnd->disp;
warning C4244: '=' : conversion from 'targ_llong' to 'targ_int', possible loss of data
2307: else if (uSizemask & _32) 2308: pc->IEVpointer1 = (targ_size_t) popnd->disp; 2309: } 2310: else 2311: { pc->IFL1 = FLblockoff; 2312: pc->IEVlsym1 = label; 2313: } 2314: } 2315: else if (s == asmstate.psLocalsize) 2316: { 2317: pc->IFL1 = FLlocalsize; 2318: pc->IEVdsym1 = NULL; 2319: pc->Iflags |= CFoff; 2320: pc->IEVoffset1 = popnd->disp;
warning C4244: '=' : conversion from 'targ_llong' to 'targ_size_t', possible loss of data
2321: } 2322: else if (s->isFuncDeclaration()) 2323: { 2324: pc->IFL1 = FLfunc; 2325: pc->IEVdsym1 = d; 2326: pc->IEVoffset1 = popnd->disp;
warning C4244: '=' : conversion from 'targ_llong' to 'targ_size_t', possible loss of data
2327: } 2328: else 2329: { 2330: #ifdef DEBUG 2331: if (debuga) 2332: printf("Setting up symbol %s\n", d->ident->toChars()); 2333: #endif 2334: pc->IFL1 = FLdsymbol; 2335: pc->IEVdsym1 = d; 2336: pc->Iflags |= CFoff; 2337: pc->IEVoffset1 = popnd->disp;
warning C4244: '=' : conversion from 'targ_llong' to 'targ_size_t', possible loss of data
2338: } 2339: } 2340: } 2341: mrmb.modregrm.reg = usFlags & NUM_MASK; 2342: 2343: if (s && (aopty == _m || aopty == _mnoi) && !s->isLabel()) 2344: { 2345: if (s == asmstate.psLocalsize) 2346: { 2347: DATA_REF: 2348: mrmb.modregrm.rm = BPRM; 2349: if (amod == _addr16 || amod == _addr32) 2350: mrmb.modregrm.mod = 0x2; 2351: else 2352: mrmb.modregrm.mod = 0x0; 2353: } 2354: else 2355: { 2356: Declaration *d = s->isDeclaration(); 2357: assert(d); 2358: if (d->isDataseg() || d->isCodeseg()) 2359: { 2360: if ((I32 && amod == _addr16) || 2361: (I16 && amod == _addr32)) 2362: asmerr(EM_bad_addr_mode); // illegal addressing mode 2363: goto DATA_REF; 2364: } 2365: mrmb.modregrm.rm = BPRM; 2366: mrmb.modregrm.mod = 0x2; 2367: } 2368: } 2369: 2370: if (aopty == _reg || amod == _rspecial) { 2371: mrmb.modregrm.mod = 0x3; 2372: mrmb.modregrm.rm |= popnd->base->val; 2373: if (popnd->base->val & NUM_MASKR) 2374: pc->Irex |= REX_B; 2375: } 2376: else if (amod == _addr16 || (amod == _flbl && I16)) 2377: { unsigned rm; 2378: 2379: #ifdef DEBUG 2380: if (debuga) 2381: printf("This is an ADDR16\n"); 2382: #endif 2383: if (!popnd->pregDisp1) 2384: { rm = 0x6; 2385: if (!s) 2386: bDisp = TRUE; 2387: } 2388: else 2389: { unsigned r1r2; 2390: #define X(r1,r2) (((r1) * 16) + (r2)) 2391: #define Y(r1) X(r1,9) 2392: 2393: 2394: if (popnd->pregDisp2) 2395: r1r2 = X(popnd->pregDisp1->val,popnd->pregDisp2->val); 2396: else 2397: r1r2 = Y(popnd->pregDisp1->val); 2398: switch (r1r2) 2399: { 2400: case X(_BX,_SI): rm = 0; break; 2401: case X(_BX,_DI): rm = 1; break; 2402: case Y(_BX): rm = 7; break; 2403: 2404: case X(_BP,_SI): rm = 2; break; 2405: case X(_BP,_DI): rm = 3; break; 2406: case Y(_BP): rm = 6; bDisp = TRUE; break; 2407: 2408: case X(_SI,_BX): rm = 0; break; 2409: case X(_SI,_BP): rm = 2; break; 2410: case Y(_SI): rm = 4; break; 2411: 2412: case X(_DI,_BX): rm = 1; break; 2413: case X(_DI,_BP): rm = 3; break; 2414: case Y(_DI): rm = 5; break; 2415: 2416: default: 2417: asmerr("bad 16 bit index address mode"); 2418: } 2419: #undef X 2420: #undef Y 2421: } 2422: mrmb.modregrm.rm = rm; 2423: 2424: #ifdef DEBUG 2425: if (debuga) 2426: printf("This is an mod = %d, popnd->s =%p, popnd->disp = %ld\n", 2427: mrmb.modregrm.mod, s, popnd->disp); 2428: #endif 2429: if (!s || (!mrmb.modregrm.mod && popnd->disp)) 2430: { 2431: if ((!popnd->disp && !bDisp) || 2432: !popnd->pregDisp1) 2433: mrmb.modregrm.mod = 0x0; 2434: else 2435: if (popnd->disp >= CHAR_MIN && 2436: popnd->disp <= SCHAR_MAX) 2437: mrmb.modregrm.mod = 0x1; 2438: else 2439: mrmb.modregrm.mod = 0X2; 2440: } 2441: else 2442: bOffsetsym = TRUE; 2443: 2444: } 2445: else if (amod == _addr32 || (amod == _flbl && I32)) 2446: { 2447: #ifdef DEBUG 2448: if (debuga) 2449: printf("This is an ADDR32\n"); 2450: #endif 2451: if (!popnd->pregDisp1) 2452: mrmb.modregrm.rm = 0x5; 2453: else if (popnd->pregDisp2 || 2454: popnd->uchMultiplier || 2455: popnd->pregDisp1->val == _ESP) 2456: { 2457: if (popnd->pregDisp2) 2458: { if (popnd->pregDisp2->val == _ESP) 2459: asmerr(EM_bad_addr_mode); // illegal addressing mode 2460: } 2461: else 2462: { if (popnd->uchMultiplier && 2463: popnd->pregDisp1->val ==_ESP) 2464: asmerr(EM_bad_addr_mode); // illegal addressing mode 2465: bDisp = TRUE; 2466: } 2467: 2468: mrmb.modregrm.rm = 0x4; 2469: bSib = TRUE; 2470: if (bDisp) 2471: { 2472: if (!popnd->uchMultiplier && 2473: popnd->pregDisp1->val==_ESP) 2474: { 2475: sib.sib.base = popnd->pregDisp1->val; 2476: sib.sib.index = 0x4; 2477: } 2478: else 2479: { 2480: #ifdef DEBUG 2481: if (debuga) 2482: printf("Resetting the mod to 0\n"); 2483: #endif 2484: if (popnd->pregDisp2) 2485: { 2486: if (popnd->pregDisp2->val != _EBP) 2487: asmerr(EM_bad_addr_mode); // illegal addressing mode 2488: } 2489: else 2490: { mrmb.modregrm.mod = 0x0; 2491: bModset = TRUE; 2492: } 2493: 2494: sib.sib.base = 0x5; 2495: sib.sib.index = popnd->pregDisp1->val; 2496: } 2497: } 2498: else 2499: { 2500: sib.sib.base = popnd->pregDisp1->val; 2501: if (popnd->pregDisp1->val & NUM_MASKR) 2502: pc->Irex |= REX_B; 2503: // 2504: // This is to handle the special case 2505: // of using the EBP (or R13) register and no 2506: // displacement. You must put in an 2507: // 8 byte displacement in order to 2508: // get the correct opcodes. 2509: // 2510: if ((popnd->pregDisp1->val == _EBP || 2511: popnd->pregDisp1->val == _R13) && 2512: (!popnd->disp && !s)) 2513: { 2514: #ifdef DEBUG 2515: if (debuga) 2516: printf("Setting the mod to 1 in the _EBP case\n"); 2517: #endif 2518: mrmb.modregrm.mod = 0x1; 2519: bDisp = TRUE; // Need a 2520: // displacement 2521: bModset = TRUE; 2522: } 2523: 2524: sib.sib.index = popnd->pregDisp2->val; 2525: if (popnd->pregDisp2->val & NUM_MASKR) 2526: pc->Irex |= REX_X; 2527: 2528: } 2529: switch (popnd->uchMultiplier) 2530: { 2531: case 0: sib.sib.ss = 0; break; 2532: case 1: sib.sib.ss = 0; break; 2533: case 2: sib.sib.ss = 1; break; 2534: case 4: sib.sib.ss = 2; break; 2535: case 8: sib.sib.ss = 3; break; 2536: 2537: default: 2538: asmerr(EM_bad_addr_mode); // illegal addressing mode 2539: break; 2540: } 2541: } 2542: else 2543: { unsigned rm; 2544: 2545: if (popnd->uchMultiplier) 2546: asmerr(EM_bad_addr_mode); // illegal addressing mode 2547: switch (popnd->pregDisp1->val) 2548: { 2549: case _EAX: rm = 0; break; 2550: case _ECX: rm = 1; break; 2551: case _EDX: rm = 2; break; 2552: case _EBX: rm = 3; break; 2553: case _ESI: rm = 6; break; 2554: case _EDI: rm = 7; break; 2555: 2556: case _EBP: 2557: if (!popnd->disp && !s) 2558: { 2559: mrmb.modregrm.mod = 0x1; 2560: bDisp = TRUE; // Need a displacement 2561: bModset = TRUE; 2562: } 2563: rm = 5; 2564: break; 2565: 2566: default: 2567: asmerr(EM_bad_addr_mode); // illegal addressing mode 2568: rm = 0; // no uninitialized data 2569: break; 2570: } 2571: mrmb.modregrm.rm = rm; 2572: } 2573: if (!bModset && (!s || 2574: (!mrmb.modregrm.mod && popnd->disp))) 2575: { 2576: if ((!popnd->disp && !mrmb.modregrm.mod) || 2577: (!popnd->pregDisp1 && !popnd->pregDisp2)) 2578: { mrmb.modregrm.mod = 0x0; 2579: bDisp = TRUE; 2580: } 2581: else if (popnd->disp >= CHAR_MIN && 2582: popnd->disp <= SCHAR_MAX) 2583: mrmb.modregrm.mod = 0x1; 2584: else 2585: mrmb.modregrm.mod = 0x2; 2586: } 2587: else 2588: bOffsetsym = TRUE; 2589: } 2590: if (popnd2 && !mrmb.modregrm.reg && 2591: asmstate.ucItype != ITshift && 2592: (ASM_GET_aopty(popnd2->usFlags) == _reg || 2593: ASM_GET_amod(popnd2->usFlags) == _rseg || 2594: ASM_GET_amod(popnd2->usFlags) == _rspecial)) 2595: { 2596: mrmb.modregrm.reg = popnd2->base->val; 2597: if (popnd2->base->val & NUM_MASKR) 2598: pc->Irex |= REX_R; 2599: } 2600: #ifdef DEBUG 2601: puchOpcode[ (*pusIdx)++ ] = mrmb.uchOpcode; 2602: #endif 2603: pc->Irm = mrmb.uchOpcode; 2604: //printf("Irm = %02x\n", pc->Irm); 2605: if (bSib) 2606: { 2607: #ifdef DEBUG 2608: puchOpcode[ (*pusIdx)++ ] = sib.uchOpcode; 2609: #endif 2610: pc->Isib= sib.uchOpcode; 2611: } 2612: if ((!s || (popnd->pregDisp1 && !bOffsetsym)) && 2613: aopty != _imm && 2614: (popnd->disp || bDisp)) 2615: { 2616: if (popnd->usFlags & _a16) 2617: { 2618: #ifdef DEBUG 2619: puc = ((unsigned char *) &(popnd->disp)); 2620: puchOpcode[(*pusIdx)++] = puc[1]; 2621: puchOpcode[(*pusIdx)++] = puc[0]; 2622: #endif 2623: if (usFlags & (_modrm | NUM_MASK)) { 2624: #ifdef DEBUG 2625: if (debuga) 2626: printf("Setting up value %ld\n", popnd->disp); 2627: #endif 2628: pc->IEVint1 = popnd->disp;
warning C4244: '=' : conversion from 'targ_llong' to 'targ_int', possible loss of data
2629: pc->IFL1 = FLconst; 2630: } 2631: else { 2632: pc->IEVint2 = popnd->disp;
warning C4244: '=' : conversion from 'targ_llong' to 'targ_int', possible loss of data
2633: pc->IFL2 = FLconst; 2634: } 2635: 2636: } 2637: else 2638: { 2639: #ifdef DEBUG 2640: puc = ((unsigned char *) &(popnd->disp)); 2641: puchOpcode[(*pusIdx)++] = puc[3]; 2642: puchOpcode[(*pusIdx)++] = puc[2]; 2643: puchOpcode[(*pusIdx)++] = puc[1]; 2644: puchOpcode[(*pusIdx)++] = puc[0]; 2645: #endif 2646: if (usFlags & (_modrm | NUM_MASK)) { 2647: #ifdef DEBUG 2648: if (debuga) 2649: printf("Setting up value %ld\n", popnd->disp); 2650: #endif 2651: pc->IEVpointer1 = (targ_size_t) popnd->disp; 2652: pc->IFL1 = FLconst; 2653: } 2654: else { 2655: pc->IEVpointer2 = (targ_size_t) popnd->disp; 2656: pc->IFL2 = FLconst; 2657: } 2658: 2659: } 2660: } 2661: } 2662: 2663: /******************************* 2664: */ 2665: 2666: STATIC regm_t asm_modify_regs(PTRNTAB ptb, OPND *popnd1, OPND *popnd2) 2667: { 2668: regm_t usRet = 0; 2669: 2670: switch (ptb.pptb0->usFlags & MOD_MASK) { 2671: case _modsi: 2672: usRet |= mSI; 2673: break; 2674: case _moddx: 2675: usRet |= mDX; 2676: break; 2677: case _mod2: 2678: if (popnd2) 2679: usRet |= asm_modify_regs(ptb, popnd2, NULL); 2680: break; 2681: case _modax: 2682: usRet |= mAX; 2683: break; 2684: case _modnot1: 2685: popnd1 = NULL; 2686: break; 2687: case _modaxdx: 2688: usRet |= (mAX | mDX); 2689: break; 2690: case _moddi: 2691: usRet |= mDI; 2692: break; 2693: case _modsidi: 2694: usRet |= (mSI | mDI); 2695: break; 2696: case _modcx: 2697: usRet |= mCX; 2698: break; 2699: case _modes: 2700: /*usRet |= mES;*/ 2701: break; 2702: case _modall: 2703: asmstate.bReturnax = TRUE; 2704: return /*mES |*/ ALLREGS; 2705: case _modsiax: 2706: usRet |= (mSI | mAX); 2707: break; 2708: case _modsinot1: 2709: usRet |= mSI; 2710: popnd1 = NULL; 2711: break; 2712: case _modcxr11: 2713: usRet |= (mCX | mR11); 2714: break; 2715: case _modxmm0: 2716: usRet |= mXMM0; 2717: break; 2718: } 2719: if (popnd1 && ASM_GET_aopty(popnd1->usFlags) == _reg) 2720: { 2721: switch (ASM_GET_amod(popnd1->usFlags)) 2722: { 2723: default: 2724: usRet |= 1 << popnd1->base->val; 2725: usRet &= ~(mBP | mSP); // ignore changing these 2726: break; 2727: 2728: case _rseg: 2729: //if (popnd1->base->val == _ES) 2730: //usRet |= mES; 2731: break; 2732: 2733: case _rspecial: 2734: break; 2735: } 2736: } 2737: if (usRet & mAX) 2738: asmstate.bReturnax = TRUE; 2739: 2740: return usRet; 2741: } 2742: 2743: /******************************* 2744: * Match flags in operand against flags in opcode table. 2745: * Returns: 2746: * !=0 if match 2747: */ 2748: 2749: STATIC unsigned char asm_match_flags(opflag_t usOp, opflag_t usTable) 2750: { 2751: ASM_OPERAND_TYPE aoptyTable; 2752: ASM_OPERAND_TYPE aoptyOp; 2753: ASM_MODIFIERS amodTable; 2754: ASM_MODIFIERS amodOp; 2755: unsigned uRegmaskTable; 2756: unsigned uRegmaskOp; 2757: unsigned char bRegmatch; 2758: unsigned char bRetval = FALSE; 2759: unsigned uSizemaskOp; 2760: unsigned uSizemaskTable; 2761: unsigned bSizematch; 2762: 2763: //printf("asm_match_flags(usOp = x%x, usTable = x%x)\n", usOp, usTable); 2764: if (asmstate.ucItype == ITfloat) 2765: { 2766: bRetval = asm_match_float_flags(usOp, usTable); 2767: goto EXIT; 2768: } 2769: 2770: uSizemaskOp = ASM_GET_uSizemask(usOp); 2771: uSizemaskTable = ASM_GET_uSizemask(usTable); 2772: 2773: // Check #1, if the sizes do not match, NO match 2774: bSizematch = (uSizemaskOp & uSizemaskTable); 2775: 2776: amodOp = ASM_GET_amod(usOp); 2777: 2778: aoptyTable = ASM_GET_aopty(usTable); 2779: aoptyOp = ASM_GET_aopty(usOp); 2780: 2781: // _mmm64 matches with a 64 bit mem or an MMX register 2782: if (usTable == _mmm64) 2783: { 2784: if (usOp == _mm) 2785: goto Lmatch; 2786: if (aoptyOp == _m && (bSizematch || uSizemaskOp == _anysize)) 2787: goto Lmatch; 2788: goto EXIT; 2789: } 2790: 2791: // _xmm_m32, _xmm_m64, _xmm_m128 match with XMM register or memory 2792: if (usTable == _xmm_m16 || 2793: usTable == _xmm_m32 || 2794: usTable == _xmm_m64 || 2795: usTable == _xmm_m128) 2796: { 2797: if (usOp == _xmm || usOp == (_xmm|_xmm0)) 2798: goto Lmatch; 2799: if (aoptyOp == _m && (bSizematch || uSizemaskOp == _anysize)) 2800: goto Lmatch; 2801: } 2802: 2803: if (!bSizematch && uSizemaskTable) 2804: { 2805: //printf("no size match\n"); 2806: goto EXIT; 2807: } 2808: 2809: 2810: // 2811: // The operand types must match, otherwise return FALSE. 2812: // There is one exception for the _rm which is a table entry which matches 2813: // _reg or _m 2814: // 2815: if (aoptyTable != aoptyOp) 2816: { 2817: if (aoptyTable == _rm && (aoptyOp == _reg || 2818: aoptyOp == _m || 2819: aoptyOp == _rel)) 2820: goto Lok; 2821: if (aoptyTable == _mnoi && aoptyOp == _m && 2822: (uSizemaskOp == _32 && amodOp == _addr16 || 2823: uSizemaskOp == _48 && amodOp == _addr32 || 2824: uSizemaskOp == _48 && amodOp == _normal) 2825: ) 2826: goto Lok; 2827: goto EXIT; 2828: } 2829: Lok: 2830: 2831: // 2832: // Looks like a match so far, check to see if anything special is going on 2833: // 2834: amodTable = ASM_GET_amod(usTable); 2835: uRegmaskOp = ASM_GET_uRegmask(usOp); 2836: uRegmaskTable = ASM_GET_uRegmask(usTable); 2837: bRegmatch = ((!uRegmaskTable && !uRegmaskOp) || 2838: (uRegmaskTable & uRegmaskOp)); 2839: 2840: switch (amodTable) 2841: { 2842: case _normal: // Normal's match with normals 2843: switch(amodOp) { 2844: case _normal: 2845: case _addr16: 2846: case _addr32: 2847: case _fn16: 2848: case _fn32: 2849: case _flbl: 2850: bRetval = (bSizematch || bRegmatch); 2851: goto EXIT; 2852: default: 2853: goto EXIT; 2854: } 2855: case _rseg: 2856: case _rspecial: 2857: bRetval = (amodOp == amodTable && bRegmatch); 2858: goto EXIT; 2859: default: 2860: assert(0); 2861: } 2862: EXIT: 2863: #if 0 2864: printf("OP : "); 2865: asm_output_flags(usOp); 2866: printf("\nTBL: "); 2867: asm_output_flags(usTable); 2868: printf(": %s\n", bRetval ? "MATCH" : "NOMATCH"); 2869: #endif 2870: return bRetval; 2871: 2872: Lmatch: 2873: //printf("match\n"); 2874: return 1; 2875: } 2876: 2877: /******************************* 2878: */ 2879: 2880: STATIC unsigned char asm_match_float_flags(opflag_t usOp, opflag_t usTable) 2881: { 2882: ASM_OPERAND_TYPE aoptyTable; 2883: ASM_OPERAND_TYPE aoptyOp; 2884: ASM_MODIFIERS amodTable; 2885: ASM_MODIFIERS amodOp; 2886: unsigned uRegmaskTable; 2887: unsigned uRegmaskOp; 2888: unsigned bRegmatch; 2889: 2890: 2891: // 2892: // Check #1, if the sizes do not match, NO match 2893: // 2894: uRegmaskOp = ASM_GET_uRegmask(usOp); 2895: uRegmaskTable = ASM_GET_uRegmask(usTable); 2896: bRegmatch = (uRegmaskTable & uRegmaskOp); 2897: 2898: if (!(ASM_GET_uSizemask(usTable) & ASM_GET_uSizemask(usOp) || 2899: bRegmatch)) 2900: return(FALSE); 2901: 2902: aoptyTable = ASM_GET_aopty(usTable); 2903: aoptyOp = ASM_GET_aopty(usOp); 2904: // 2905: // The operand types must match, otherwise return FALSE. 2906: // There is one exception for the _rm which is a table entry which matches 2907: // _reg or _m 2908: // 2909: if (aoptyTable != aoptyOp) 2910: { 2911: if (aoptyOp != _float) 2912: return(FALSE); 2913: } 2914: 2915: // 2916: // Looks like a match so far, check to see if anything special is going on 2917: // 2918: amodOp = ASM_GET_amod(usOp); 2919: amodTable = ASM_GET_amod(usTable); 2920: switch (amodTable) 2921: { 2922: // Normal's match with normals 2923: case _normal: 2924: switch(amodOp) 2925: { 2926: case _normal: 2927: case _addr16: 2928: case _addr32: 2929: case _fn16: 2930: case _fn32: 2931: case _flbl: 2932: return(TRUE); 2933: default: 2934: return(FALSE); 2935: } 2936: case _rseg: 2937: case _rspecial: 2938: return(FALSE); 2939: default: 2940: assert(0); 2941: return 0; 2942: } 2943: } 2944: 2945: #ifdef DEBUG 2946: 2947: /******************************* 2948: */ 2949: 2950: STATIC void asm_output_flags(opflag_t opflags) 2951: { 2952: ASM_OPERAND_TYPE aopty = ASM_GET_aopty(opflags); 2953: ASM_MODIFIERS amod = ASM_GET_amod(opflags); 2954: unsigned uRegmask = ASM_GET_uRegmask(opflags); 2955: unsigned uSizemask = ASM_GET_uSizemask(opflags); 2956: 2957: if (uSizemask == _anysize) 2958: printf("_anysize "); 2959: else if (uSizemask == 0) 2960: printf("0 "); 2961: else 2962: { 2963: if (uSizemask & _8) 2964: printf("_8 "); 2965: if (uSizemask & _16) 2966: printf("_16 "); 2967: if (uSizemask & _32) 2968: printf("_32 "); 2969: if (uSizemask & _48) 2970: printf("_48 "); 2971: if (uSizemask & _64) 2972: printf("_64 "); 2973: } 2974: 2975: printf("_"); 2976: switch (aopty) { 2977: case _reg: 2978: printf("reg "); 2979: break; 2980: case _m: 2981: printf("m "); 2982: break; 2983: case _imm: 2984: printf("imm "); 2985: break; 2986: case _rel: 2987: printf("rel "); 2988: break; 2989: case _mnoi: 2990: printf("mnoi "); 2991: break; 2992: case _p: 2993: printf("p "); 2994: break; 2995: case _rm: 2996: printf("rm "); 2997: break; 2998: case _float: 2999: printf("float "); 3000: break; 3001: default: 3002: printf(" UNKNOWN "); 3003: } 3004: 3005: printf("_"); 3006: switch (amod) { 3007: case _normal: 3008: printf("normal "); 3009: if (uRegmask & 1) printf("_al "); 3010: if (uRegmask & 2) printf("_ax "); 3011: if (uRegmask & 4) printf("_eax "); 3012: if (uRegmask & 8) printf("_dx "); 3013: if (uRegmask & 0x10) printf("_cl "); 3014: if (uRegmask & 0x40) printf("_rax "); 3015: if (uRegmask & 0x20) printf("_rplus_r "); 3016: return; 3017: case _rseg: 3018: printf("rseg "); 3019: break; 3020: case _rspecial: 3021: printf("rspecial "); 3022: break; 3023: case _addr16: 3024: printf("addr16 "); 3025: break; 3026: case _addr32: 3027: printf("addr32 "); 3028: break; 3029: case _fn16: 3030: printf("fn16 "); 3031: break; 3032: case _fn32: 3033: printf("fn32 "); 3034: break; 3035: case _flbl: 3036: printf("flbl "); 3037: break; 3038: default: 3039: printf("UNKNOWN "); 3040: break; 3041: } 3042: printf("uRegmask=x%02x", uRegmask); 3043: 3044: } 3045: 3046: /******************************* 3047: */ 3048: 3049: STATIC void asm_output_popnd(OPND *popnd) 3050: { 3051: if (popnd->segreg) 3052: printf("%s:", popnd->segreg->regstr); 3053: 3054: if (popnd->s) 3055: printf("%s", popnd->s->ident->toChars()); 3056: 3057: if (popnd->base) 3058: printf("%s", popnd->base->regstr); 3059: if (popnd->pregDisp1) { 3060: if (popnd->pregDisp2) { 3061: if (popnd->usFlags & _a32) 3062: if (popnd->uchMultiplier) 3063: printf("[%s][%s*%d]", 3064: popnd->pregDisp1->regstr, 3065: popnd->pregDisp2->regstr, 3066: popnd->uchMultiplier); 3067: else 3068: printf("[%s][%s]", 3069: popnd->pregDisp1->regstr, 3070: popnd->pregDisp2->regstr); 3071: else 3072: printf("[%s+%s]", 3073: popnd->pregDisp1->regstr, 3074: popnd->pregDisp2->regstr); 3075: } 3076: else { 3077: if (popnd->uchMultiplier) 3078: printf("[%s*%d]", 3079: popnd->pregDisp1->regstr, 3080: popnd->uchMultiplier); 3081: else 3082: printf("[%s]", 3083: popnd->pregDisp1->regstr); 3084: } 3085: } 3086: if (ASM_GET_aopty(popnd->usFlags) == _imm) 3087: printf("%lxh", popnd->disp); 3088: else 3089: if (popnd->disp) 3090: printf("+%lxh", popnd->disp); 3091: } 3092: 3093: #endif 3094: 3095: /******************************* 3096: */ 3097: 3098: STATIC REG *asm_reg_lookup(char *s) 3099: { 3100: int i; 3101: 3102: //dbg_printf("asm_reg_lookup('%s')\n",s); 3103: 3104: for (i = 0; i < sizeof(regtab) / sizeof(regtab[0]); i++) 3105: { 3106: if (strcmp(s,regtab[i].regstr) == 0) 3107: { 3108: return &regtab[i]; 3109: } 3110: } 3111: if (I64) 3112: { 3113: for (i = 0; i < sizeof(regtab64) / sizeof(regtab64[0]); i++) 3114: { 3115: if (strcmp(s,regtab64[i].regstr) == 0) 3116: { 3117: return &regtab64[i]; 3118: } 3119: } 3120: } 3121: return NULL; 3122: } 3123: 3124: 3125: /******************************* 3126: */ 3127: 3128: STATIC void asm_token() 3129: { 3130: if (asmtok) 3131: asmtok = asmtok->next; 3132: asm_token_trans(asmtok); 3133: } 3134: 3135: /******************************* 3136: */ 3137: 3138: STATIC void asm_token_trans(Token *tok)
warning C6244: Local declaration of 'tok' hides previous declaration at line '315' of 'c:\projects\extern\d\dmd\src\backend\token.h'
3139: { 3140: tok_value = TOKeof; 3141: if (tok) 3142: { 3143: tok_value = tok->value; 3144: if (tok_value == TOKidentifier) 3145: { size_t len; 3146: char *id; 3147: 3148: id = tok->ident->toChars(); 3149: len = strlen(id); 3150: if (len < 20) 3151: { 3152: ASMTK asmtk = (ASMTK) binary(id, apszAsmtk, ASMTKmax); 3153: if ((int)asmtk >= 0) 3154: tok_value = (enum TOK) (asmtk + TOKMAX + 1); 3155: } 3156: } 3157: } 3158: } 3159: 3160: /******************************* 3161: */ 3162: 3163: STATIC unsigned asm_type_size(Type * ptype) 3164: { unsigned u; 3165: 3166: //if (ptype) printf("asm_type_size('%s') = %d\n", ptype->toChars(), (int)ptype->size()); 3167: u = _anysize; 3168: if (ptype && ptype->ty != Tfunction /*&& ptype->isscalar()*/) 3169: { 3170: switch ((int)ptype->size()) 3171: { 3172: case 0: asmerr(EM_bad_op, "0 size"); break; 3173: case 1: u = _8; break; 3174: case 2: u = _16; break; 3175: case 4: u = _32; break; 3176: case 6: u = _48; break; 3177: case 8: if (I64) u = _64; break; 3178: } 3179: } 3180: return u; 3181: } 3182: 3183: /******************************* 3184: * start of inline assemblers expression parser 3185: * NOTE: functions in call order instead of alphabetical 3186: */ 3187: 3188: /******************************************* 3189: * Parse DA expression 3190: * 3191: * Very limited define address to place a code 3192: * address in the assembly 3193: * Problems: 3194: * o Should use dw offset and dd offset instead, 3195: * for near/far support. 3196: * o Should be able to add an offset to the label address. 3197: * o Blocks addressed by DA should get their Bpred set correctly 3198: * for optimizer. 3199: */ 3200: 3201: STATIC code *asm_da_parse(OP *pop) 3202: { 3203: code *clst = NULL; 3204: elem *e;
warning C4101: 'e' : unreferenced local variable
3205: 3206: while (1) 3207: { code *c; 3208: 3209: if (tok_value == TOKidentifier) 3210: { 3211: LabelDsymbol *label; 3212: 3213: label = asmstate.sc->func->searchLabel(asmtok->ident); 3214: if (!label) 3215: error(asmstate.loc, "label '%s' not found\n", asmtok->ident->toChars()); 3216: 3217: c = code_calloc(); 3218: c->Iop = ASM; 3219: c->Iflags = CFaddrsize; 3220: c->IFL1 = FLblockoff; 3221: c->IEVlsym1 = label; 3222: c = asm_genloc(asmstate.loc, c); 3223: clst = cat(clst,c); 3224: } 3225: else 3226: asmerr(EM_bad_addr_mode); // illegal addressing mode 3227: asm_token(); 3228: if (tok_value != TOKcomma) 3229: break; 3230: asm_token(); 3231: } 3232: 3233: asmstate.statement->regs |= mES|ALLREGS; 3234: asmstate.bReturnax = TRUE; 3235: 3236: return clst; 3237: } 3238: 3239: /******************************************* 3240: * Parse DB, DW, DD, DQ and DT expressions. 3241: */ 3242: 3243: STATIC code *asm_db_parse(OP *pop) 3244: { 3245: unsigned usSize; 3246: unsigned usMaxbytes; 3247: unsigned usBytes; 3248: union DT 3249: { targ_ullong ul; 3250: targ_float f; 3251: targ_double d; 3252: targ_ldouble ld; 3253: char value[10]; 3254: } dt; 3255: code *c; 3256: unsigned op; 3257: static unsigned char opsize[] = { 1,2,4,8,4,8,10 }; 3258: 3259: op = pop->usNumops & ITSIZE; 3260: usSize = opsize[op]; 3261: 3262: usBytes = 0; 3263: usMaxbytes = 0; 3264: c = code_calloc(); 3265: c->Iop = ASM; 3266: 3267: while (1) 3268: { 3269: size_t len; 3270: unsigned char *q; 3271: 3272: if (usBytes+usSize > usMaxbytes) 3273: { usMaxbytes = usBytes + usSize + 10; 3274: c->IEV1.as.bytes = (char *)mem_realloc(c->IEV1.as.bytes,usMaxbytes); 3275: } 3276: switch (tok_value) 3277: { 3278: case TOKint32v: 3279: dt.ul = asmtok->int32value; 3280: goto L1; 3281: case TOKuns32v: 3282: dt.ul = asmtok->uns32value; 3283: goto L1; 3284: case TOKint64v: 3285: dt.ul = asmtok->int64value; 3286: goto L1; 3287: case TOKuns64v: 3288: dt.ul = asmtok->uns64value; 3289: goto L1; 3290: L1: 3291: switch (op) 3292: { 3293: case OPdb: 3294: case OPds: 3295: case OPdi: 3296: case OPdl: 3297: break; 3298: default: 3299: asmerr(EM_float); 3300: } 3301: goto L2; 3302: 3303: case TOKfloat32v: 3304: case TOKfloat64v: 3305: case TOKfloat80v: 3306: switch (op) 3307: { 3308: case OPdf: 3309: dt.f = asmtok->float80value;
warning C4244: '=' : conversion from 'd_float80' to 'targ_float', possible loss of data
3310: break; 3311: case OPdd: 3312: dt.d = asmtok->float80value; 3313: break; 3314: case OPde: 3315: dt.ld = asmtok->float80value; 3316: break; 3317: default: 3318: asmerr(EM_num); 3319: } 3320: goto L2; 3321: 3322: L2: 3323: memcpy(c->IEV1.as.bytes + usBytes,&dt,usSize);
warning C6001: Using uninitialized memory 'dt': Lines: 3245, 3246, 3247, 3248, 3254, 3255, 3256, 3257, 3259, 3260, 3262, 3263, 3264, 3265, 3267, 3269, 3270, 3272, 3276, 3303, 3304, 3305, 3306, 3317, 3318, 3320, 3322, 3323
3324: usBytes += usSize; 3325: break; 3326: 3327: case TOKstring: 3328: len = asmtok->len; 3329: q = asmtok->ustring; 3330: L3: 3331: if (len) 3332: { 3333: usMaxbytes += len * usSize; 3334: c->IEV1.as.bytes = 3335: (char *)mem_realloc(c->IEV1.as.bytes,usMaxbytes); 3336: memcpy(c->IEV1.as.bytes + usBytes,asmtok->ustring,len); 3337: 3338: char *p = c->IEV1.as.bytes + usBytes; 3339: for (size_t i = 0; i < len; i++) 3340: { 3341: // Be careful that this works 3342: memset(p, 0, usSize); 3343: switch (op) 3344: { 3345: case OPdb: 3346: *p = (unsigned char)*q; 3347: if (*p != *q) 3348: asmerr(EM_char); 3349: break; 3350: 3351: case OPds: 3352: *(short *)p = *(unsigned char *)q; 3353: if (*(short *)p != *q) 3354: asmerr(EM_char); 3355: break; 3356: 3357: case OPdi: 3358: case OPdl: 3359: *(long *)p = *q; 3360: break; 3361: 3362: default: 3363: asmerr(EM_float); 3364: } 3365: q++; 3366: p += usSize; 3367: } 3368: 3369: usBytes += len * usSize; 3370: } 3371: break; 3372: 3373: case TOKidentifier: 3374: { Expression *e = new IdentifierExp(asmstate.loc, asmtok->ident); 3375: e = e->semantic(asmstate.sc); 3376: e = e->optimize(WANTvalue | WANTinterpret); 3377: if (e->op == TOKint64) 3378: { dt.ul = e->toInteger(); 3379: goto L2; 3380: } 3381: else if (e->op == TOKfloat64) 3382: { 3383: switch (op) 3384: { 3385: case OPdf: 3386: dt.f = e->toReal();
warning C4244: '=' : conversion from 'real_t' to 'targ_float', possible loss of data
3387: break; 3388: case OPdd: 3389: dt.d = e->toReal(); 3390: break; 3391: case OPde: 3392: dt.ld = e->toReal(); 3393: break; 3394: default: 3395: asmerr(EM_num); 3396: } 3397: goto L2; 3398: } 3399: else if (e->op == TOKstring) 3400: { StringExp *se = (StringExp *)e; 3401: q = (unsigned char *)se->string; 3402: len = se->len; 3403: goto L3; 3404: } 3405: goto Ldefault; 3406: } 3407: 3408: default: 3409: Ldefault: 3410: asmerr(EM_const_init); // constant initializer 3411: break; 3412: } 3413: c->IEV1.as.len = usBytes; 3414: 3415: asm_token(); 3416: if (tok_value != TOKcomma) 3417: break; 3418: asm_token(); 3419: } 3420: 3421: c = asm_genloc(asmstate.loc, c); 3422: 3423: asmstate.statement->regs |= /* mES| */ ALLREGS; 3424: asmstate.bReturnax = TRUE; 3425: 3426: return c; 3427: } 3428: 3429: /********************************** 3430: * Parse and get integer expression. 3431: */ 3432: 3433: int asm_getnum() 3434: { int v; 3435: dinteger_t i; 3436: 3437: switch (tok_value) 3438: { 3439: case TOKint32v: 3440: v = asmtok->int32value; 3441: break; 3442: 3443: case TOKuns32v: 3444: v = asmtok->uns32value; 3445: break; 3446: 3447: case TOKidentifier: 3448: Expression *e; 3449: 3450: e = new IdentifierExp(asmstate.loc, asmtok->ident); 3451: e = e->semantic(asmstate.sc); 3452: e = e->optimize(WANTvalue | WANTinterpret); 3453: i = e->toInteger(); 3454: v = (int) i; 3455: if (v != i) 3456: asmerr(EM_num); 3457: break; 3458: 3459: default: 3460: asmerr(EM_num); 3461: v = 0; // no uninitialized values 3462: break; 3463: } 3464: asm_token(); 3465: return v; 3466: } 3467: 3468: /******************************* 3469: */ 3470: 3471: STATIC OPND *asm_cond_exp() 3472: { 3473: OPND *o1,*o2,*o3; 3474: 3475: //printf("asm_cond_exp()\n"); 3476: o1 = asm_log_or_exp(); 3477: if (tok_value == TOKquestion) 3478: { 3479: asm_token(); 3480: o2 = asm_cond_exp(); 3481: asm_token(); 3482: asm_chktok(TOKcolon,EM_colon); 3483: o3 = asm_cond_exp(); 3484: o1 = (o1->disp) ? o2 : o3; 3485: } 3486: return o1; 3487: } 3488: 3489: /******************************* 3490: */ 3491: 3492: STATIC OPND *asm_log_or_exp() 3493: { 3494: OPND *o1,*o2; 3495: 3496: o1 = asm_log_and_exp(); 3497: while (tok_value == TOKoror) 3498: { 3499: asm_token(); 3500: o2 = asm_log_and_exp(); 3501: if (asm_isint(o1) && asm_isint(o2)) 3502: o1->disp = o1->disp || o2->disp; 3503: else 3504: asmerr(EM_bad_integral_operand); // illegal operand 3505: o2->disp = 0; 3506: o1 = asm_merge_opnds(o1, o2); 3507: } 3508: return o1; 3509: } 3510: 3511: /******************************* 3512: */ 3513: 3514: STATIC OPND *asm_log_and_exp() 3515: { 3516: OPND *o1,*o2; 3517: 3518: o1 = asm_inc_or_exp(); 3519: while (tok_value == TOKandand) 3520: { 3521: asm_token(); 3522: o2 = asm_inc_or_exp(); 3523: if (asm_isint(o1) && asm_isint(o2)) 3524: o1->disp = o1->disp && o2->disp; 3525: else { 3526: asmerr(EM_bad_integral_operand); // illegal operand 3527: } 3528: o2->disp = 0; 3529: o1 = asm_merge_opnds(o1, o2); 3530: } 3531: return o1; 3532: } 3533: 3534: /******************************* 3535: */ 3536: 3537: STATIC OPND *asm_inc_or_exp() 3538: { 3539: OPND *o1,*o2; 3540: 3541: o1 = asm_xor_exp(); 3542: while (tok_value == TOKor) 3543: { 3544: asm_token(); 3545: o2 = asm_xor_exp(); 3546: if (asm_isint(o1) && asm_isint(o2)) 3547: o1->disp |= o2->disp; 3548: else { 3549: asmerr(EM_bad_integral_operand); // illegal operand 3550: } 3551: o2->disp = 0; 3552: o1 = asm_merge_opnds(o1, o2); 3553: } 3554: return o1; 3555: } 3556: 3557: /******************************* 3558: */ 3559: 3560: STATIC OPND *asm_xor_exp() 3561: { 3562: OPND *o1,*o2; 3563: 3564: o1 = asm_and_exp(); 3565: while (tok_value == TOKxor) 3566: { 3567: asm_token(); 3568: o2 = asm_and_exp(); 3569: if (asm_isint(o1) && asm_isint(o2)) 3570: o1->disp ^= o2->disp; 3571: else { 3572: asmerr(EM_bad_integral_operand); // illegal operand 3573: } 3574: o2->disp = 0; 3575: o1 = asm_merge_opnds(o1, o2); 3576: } 3577: return o1; 3578: } 3579: 3580: /******************************* 3581: */ 3582: 3583: STATIC OPND *asm_and_exp() 3584: { 3585: OPND *o1,*o2; 3586: 3587: o1 = asm_equal_exp(); 3588: while (tok_value == TOKand) 3589: { 3590: asm_token(); 3591: o2 = asm_equal_exp(); 3592: if (asm_isint(o1) && asm_isint(o2)) 3593: o1->disp &= o2->disp; 3594: else { 3595: asmerr(EM_bad_integral_operand); // illegal operand 3596: } 3597: o2->disp = 0; 3598: o1 = asm_merge_opnds(o1, o2); 3599: } 3600: return o1; 3601: } 3602: 3603: /******************************* 3604: */ 3605: 3606: STATIC OPND *asm_equal_exp() 3607: { 3608: OPND *o1,*o2; 3609: 3610: o1 = asm_rel_exp(); 3611: while (1) 3612: { 3613: switch (tok_value) 3614: { 3615: case TOKequal: 3616: asm_token(); 3617: o2 = asm_rel_exp(); 3618: if (asm_isint(o1) && asm_isint(o2)) 3619: o1->disp = o1->disp == o2->disp; 3620: else { 3621: asmerr(EM_bad_integral_operand); // illegal operand 3622: } 3623: o2->disp = 0; 3624: o1 = asm_merge_opnds(o1, o2); 3625: break; 3626: 3627: case TOKnotequal: 3628: asm_token(); 3629: o2 = asm_rel_exp(); 3630: if (asm_isint(o1) && asm_isint(o2)) 3631: o1->disp = o1->disp != o2->disp; 3632: else { 3633: asmerr(EM_bad_integral_operand); 3634: } 3635: o2->disp = 0; 3636: o1 = asm_merge_opnds(o1, o2); 3637: break; 3638: 3639: default: 3640: return o1; 3641: } 3642: } 3643: } 3644: 3645: /******************************* 3646: */ 3647: 3648: STATIC OPND *asm_rel_exp() 3649: { 3650: OPND *o1,*o2; 3651: enum TOK tok_save; 3652: 3653: o1 = asm_shift_exp(); 3654: while (1) 3655: { 3656: switch (tok_value) 3657: { 3658: case TOKgt: 3659: case TOKge: 3660: case TOKlt: 3661: case TOKle: 3662: tok_save = tok_value; 3663: asm_token(); 3664: o2 = asm_shift_exp(); 3665: if (asm_isint(o1) && asm_isint(o2)) 3666: { 3667: switch (tok_save) 3668: { 3669: case TOKgt: 3670: o1->disp = o1->disp > o2->disp; 3671: break; 3672: case TOKge: 3673: o1->disp = o1->disp >= o2->disp; 3674: break; 3675: case TOKlt: 3676: o1->disp = o1->disp < o2->disp; 3677: break; 3678: case TOKle: 3679: o1->disp = o1->disp <= o2->disp; 3680: break; 3681: } 3682: } 3683: else 3684: asmerr(EM_bad_integral_operand); 3685: o2->disp = 0; 3686: o1 = asm_merge_opnds(o1, o2); 3687: break; 3688: 3689: default: 3690: return o1; 3691: } 3692: } 3693: } 3694: 3695: /******************************* 3696: */ 3697: 3698: STATIC OPND *asm_shift_exp() 3699: { 3700: OPND *o1,*o2; 3701: int op;
warning C4101: 'op' : unreferenced local variable
3702: enum TOK tk; 3703: 3704: o1 = asm_add_exp(); 3705: while (tok_value == TOKshl || tok_value == TOKshr || tok_value == TOKushr) 3706: { tk = tok_value; 3707: asm_token(); 3708: o2 = asm_add_exp(); 3709: if (asm_isint(o1) && asm_isint(o2)) 3710: { if (tk == TOKshl) 3711: o1->disp <<= o2->disp; 3712: else if (tk == TOKushr) 3713: o1->disp = (unsigned)o1->disp >> o2->disp; 3714: else 3715: o1->disp >>= o2->disp; 3716: } 3717: else 3718: asmerr(EM_bad_integral_operand); 3719: o2->disp = 0; 3720: o1 = asm_merge_opnds(o1, o2); 3721: } 3722: return o1; 3723: } 3724: 3725: /******************************* 3726: */ 3727: 3728: STATIC OPND *asm_add_exp() 3729: { 3730: OPND *o1,*o2; 3731: 3732: o1 = asm_mul_exp(); 3733: while (1) 3734: { 3735: switch (tok_value) 3736: { 3737: case TOKadd: 3738: asm_token(); 3739: o2 = asm_mul_exp(); 3740: o1 = asm_merge_opnds(o1, o2); 3741: break; 3742: 3743: case TOKmin: 3744: asm_token(); 3745: o2 = asm_mul_exp(); 3746: if (asm_isint(o1) && asm_isint(o2)) 3747: { 3748: o1->disp -= o2->disp; 3749: o2->disp = 0; 3750: } 3751: else 3752: o2->disp = - o2->disp; 3753: o1 = asm_merge_opnds(o1, o2); 3754: break; 3755: 3756: default: 3757: return o1; 3758: } 3759: } 3760: } 3761: 3762: /******************************* 3763: */ 3764: 3765: STATIC OPND *asm_mul_exp() 3766: { 3767: OPND *o1,*o2; 3768: OPND *popndTmp; 3769: 3770: //printf("+asm_mul_exp()\n"); 3771: o1 = asm_br_exp(); 3772: while (1) 3773: { 3774: switch (tok_value) 3775: { 3776: case TOKmul: 3777: asm_token(); 3778: o2 = asm_br_exp(); 3779: #ifdef EXTRA_DEBUG 3780: printf("Star o1.isint=%d, o2.isint=%d, lbra_seen=%d\n", 3781: asm_isint(o1), asm_isint(o2), asm_TKlbra_seen ); 3782: #endif 3783: if (asm_isNonZeroInt(o1) && asm_isNonZeroInt(o2)) 3784: o1->disp *= o2->disp; 3785: else if (asm_TKlbra_seen && o1->pregDisp1 && asm_isNonZeroInt(o2)) 3786: { 3787: o1->uchMultiplier = o2->disp;
warning C4244: '=' : conversion from 'targ_llong' to 'unsigned int', possible loss of data
3788: #ifdef EXTRA_DEBUG 3789: printf("Multiplier: %d\n", o1->uchMultiplier); 3790: #endif 3791: } 3792: else if (asm_TKlbra_seen && o2->pregDisp1 && asm_isNonZeroInt(o1)) 3793: { 3794: popndTmp = o2; 3795: o2 = o1; 3796: o1 = popndTmp; 3797: o1->uchMultiplier = o2->disp;
warning C4244: '=' : conversion from 'targ_llong' to 'unsigned int', possible loss of data
3798: #ifdef EXTRA_DEBUG 3799: printf("Multiplier: %d\n", 3800: o1->uchMultiplier); 3801: #endif 3802: } 3803: else if (asm_isint(o1) && asm_isint(o2)) 3804: o1->disp *= o2->disp; 3805: else 3806: asmerr(EM_bad_operand); 3807: o2->disp = 0; 3808: o1 = asm_merge_opnds(o1, o2); 3809: break; 3810: 3811: case TOKdiv: 3812: asm_token(); 3813: o2 = asm_br_exp(); 3814: if (asm_isint(o1) && asm_isint(o2)) 3815: o1->disp /= o2->disp; 3816: else 3817: asmerr(EM_bad_integral_operand); 3818: o2->disp = 0; 3819: o1 = asm_merge_opnds(o1, o2); 3820: break; 3821: 3822: case TOKmod: 3823: asm_token(); 3824: o2 = asm_br_exp(); 3825: if (asm_isint(o1) && asm_isint(o2)) 3826: o1->disp %= o2->disp; 3827: else 3828: asmerr(EM_bad_integral_operand); 3829: o2->disp = 0; 3830: o1 = asm_merge_opnds(o1, o2); 3831: break; 3832: 3833: default: 3834: return o1; 3835: } 3836: } 3837: return o1; 3838: } 3839: 3840: /******************************* 3841: */ 3842: 3843: STATIC OPND *asm_br_exp() 3844: { 3845: OPND *o1,*o2; 3846: Declaration *s;
warning C4101: 's' : unreferenced local variable
3847: 3848: //printf("asm_br_exp()\n"); 3849: o1 = asm_una_exp(); 3850: while (1) 3851: { 3852: switch (tok_value) 3853: { 3854: case TOKlbracket: 3855: { 3856: #ifdef EXTRA_DEBUG 3857: printf("Saw a left bracket\n"); 3858: #endif 3859: asm_token(); 3860: asm_TKlbra_seen++; 3861: o2 = asm_cond_exp(); 3862: asm_TKlbra_seen--; 3863: asm_chktok(TOKrbracket,EM_rbra); 3864: #ifdef EXTRA_DEBUG 3865: printf("Saw a right bracket\n"); 3866: #endif 3867: o1 = asm_merge_opnds(o1, o2); 3868: if (tok_value == TOKidentifier) 3869: { o2 = asm_una_exp(); 3870: o1 = asm_merge_opnds(o1, o2); 3871: } 3872: break; 3873: } 3874: default: 3875: return o1; 3876: } 3877: } 3878: } 3879: 3880: /******************************* 3881: */ 3882: 3883: STATIC OPND *asm_una_exp() 3884: { 3885: OPND *o1; 3886: int op;
warning C4101: 'op' : unreferenced local variable
3887: Type *ptype; 3888: Type *ptypeSpec;
warning C4101: 'ptypeSpec' : unreferenced local variable
3889: ASM_JUMPTYPE ajt = ASM_JUMPTYPE_UNSPECIFIED; 3890: char bPtr = 0; 3891: 3892: switch (tok_value) 3893: { 3894: #if 0 3895: case TOKand: 3896: asm_token(); 3897: o1 = asm_una_exp(); 3898: break; 3899: 3900: case TOKmul: 3901: asm_token(); 3902: o1 = asm_una_exp(); 3903: ++o1->indirect; 3904: break; 3905: #endif 3906: case TOKadd: 3907: asm_token(); 3908: o1 = asm_una_exp(); 3909: break; 3910: 3911: case TOKmin: 3912: asm_token(); 3913: o1 = asm_una_exp(); 3914: if (asm_isint(o1)) 3915: o1->disp = -o1->disp; 3916: break; 3917: 3918: case TOKnot: 3919: asm_token(); 3920: o1 = asm_una_exp(); 3921: if (asm_isint(o1)) 3922: o1->disp = !o1->disp; 3923: break; 3924: 3925: case TOKtilde: 3926: asm_token(); 3927: o1 = asm_una_exp(); 3928: if (asm_isint(o1)) 3929: o1->disp = ~o1->disp; 3930: break; 3931: 3932: #if 0 3933: case TOKlparen: 3934: // stoken() is called directly here because we really 3935: // want the INT token to be an INT. 3936: stoken(); 3937: if (type_specifier(&ptypeSpec)) /* if type_name */ 3938: { 3939: 3940: ptype = declar_abstract(ptypeSpec); 3941: /* read abstract_declarator */ 3942: fixdeclar(ptype);/* fix declarator */ 3943: type_free(ptypeSpec);/* the declar() function 3944: allocates the typespec again */ 3945: chktok(TOKrparen,EM_rpar); 3946: ptype->Tcount--; 3947: goto CAST_REF; 3948: } 3949: else 3950: { 3951: type_free(ptypeSpec); 3952: o1 = asm_cond_exp(); 3953: chktok(TOKrparen, EM_rpar); 3954: } 3955: break; 3956: #endif 3957: 3958: case TOKidentifier: 3959: // Check for offset keyword 3960: if (asmtok->ident == Id::offset) 3961: { 3962: if (!global.params.useDeprecated) 3963: error(asmstate.loc, "offset deprecated, use offsetof"); 3964: goto Loffset; 3965: } 3966: if (asmtok->ident == Id::offsetof) 3967: { 3968: Loffset: 3969: asm_token(); 3970: o1 = asm_cond_exp(); 3971: if (!o1) 3972: o1 = opnd_calloc(); 3973: o1->bOffset= TRUE; 3974: } 3975: else 3976: o1 = asm_primary_exp(); 3977: break; 3978: 3979: case ASMTKseg: 3980: asm_token(); 3981: o1 = asm_cond_exp(); 3982: if (!o1) 3983: o1 = opnd_calloc(); 3984: o1->bSeg= TRUE; 3985: break; 3986: 3987: case TOKint16: 3988: if (asmstate.ucItype != ITjump) 3989: { 3990: ptype = Type::tint16; 3991: goto TYPE_REF; 3992: } 3993: ajt = ASM_JUMPTYPE_SHORT; 3994: asm_token(); 3995: goto JUMP_REF2; 3996: 3997: case ASMTKnear: 3998: ajt = ASM_JUMPTYPE_NEAR; 3999: goto JUMP_REF; 4000: 4001: case ASMTKfar: 4002: ajt = ASM_JUMPTYPE_FAR; 4003: JUMP_REF: 4004: asm_token(); 4005: asm_chktok((enum TOK) ASMTKptr, EM_ptr_exp); 4006: JUMP_REF2: 4007: o1 = asm_cond_exp(); 4008: if (!o1) 4009: o1 = opnd_calloc(); 4010: o1->ajt= ajt; 4011: break; 4012: 4013: case TOKint8: 4014: ptype = Type::tint8; 4015: goto TYPE_REF; 4016: case TOKint32: 4017: case ASMTKdword: 4018: ptype = Type::tint32; 4019: goto TYPE_REF; 4020: case TOKfloat32: 4021: ptype = Type::tfloat32; 4022: goto TYPE_REF; 4023: case ASMTKqword: 4024: case TOKfloat64: 4025: ptype = Type::tfloat64; 4026: goto TYPE_REF; 4027: case TOKfloat80: 4028: ptype = Type::tfloat80; 4029: goto TYPE_REF; 4030: case ASMTKword: 4031: ptype = Type::tint16; 4032: TYPE_REF: 4033: bPtr = 1; 4034: asm_token(); 4035: asm_chktok((enum TOK) ASMTKptr, EM_ptr_exp); 4036: CAST_REF:
warning C4102: 'CAST_REF' : unreferenced label
4037: o1 = asm_cond_exp(); 4038: if (!o1) 4039: o1 = opnd_calloc(); 4040: o1->ptype = ptype; 4041: o1->bPtr = bPtr; 4042: break; 4043: 4044: default: 4045: o1 = asm_primary_exp(); 4046: break; 4047: } 4048: return o1; 4049: } 4050: 4051: /******************************* 4052: */ 4053: 4054: STATIC OPND *asm_primary_exp() 4055: { 4056: OPND *o1 = NULL; 4057: OPND *o2 = NULL; 4058: Type *ptype;
warning C4101: 'ptype' : unreferenced local variable
4059: Dsymbol *s; 4060: Dsymbol *scopesym; 4061: 4062: enum TOK tkOld;
warning C4101: 'tkOld' : unreferenced local variable
4063: REG *regp; 4064: 4065: switch (tok_value) 4066: { 4067: case TOKdollar: 4068: o1 = opnd_calloc(); 4069: o1->s = asmstate.psDollar; 4070: asm_token(); 4071: break; 4072: 4073: #if 0 4074: case TOKthis: 4075: strcpy(tok.TKid,cpp_name_this); 4076: #endif 4077: case TOKthis: 4078: case TOKidentifier: 4079: case_ident:
warning C4102: 'case_ident' : unreferenced label
4080: o1 = opnd_calloc(); 4081: regp = asm_reg_lookup(asmtok->ident->toChars()); 4082: if (regp != NULL) 4083: { 4084: asm_token(); 4085: // see if it is segment override (like SS:) 4086: if (!asm_TKlbra_seen && 4087: (regp->ty & _seg) && 4088: tok_value == TOKcolon) 4089: { 4090: o1->segreg = regp; 4091: asm_token(); 4092: o2 = asm_cond_exp(); 4093: o1 = asm_merge_opnds(o1, o2); 4094: } 4095: else if (asm_TKlbra_seen) 4096: { // should be a register 4097: if (o1->pregDisp1) 4098: asmerr(EM_bad_operand); 4099: else 4100: o1->pregDisp1 = regp; 4101: } 4102: else 4103: { if (o1->base == NULL) 4104: o1->base = regp; 4105: else 4106: asmerr(EM_bad_operand); 4107: } 4108: break; 4109: } 4110: // If floating point instruction and id is a floating register 4111: else if (asmstate.ucItype == ITfloat && 4112: asm_is_fpreg(asmtok->ident->toChars())) 4113: { 4114: asm_token(); 4115: if (tok_value == TOKlparen) 4116: { unsigned n; 4117: 4118: asm_token(); 4119: asm_chktok(TOKint32v, EM_num); 4120: n = (unsigned)asmtok->uns64value; 4121: if (n > 7) 4122: asmerr(EM_bad_operand); 4123: o1->base = &(aregFp[n]); 4124: asm_chktok(TOKrparen, EM_rpar); 4125: } 4126: else 4127: o1->base = &regFp; 4128: } 4129: else 4130: { 4131: if (asmstate.ucItype == ITjump) 4132: { 4133: s = NULL; 4134: if (asmstate.sc->func->labtab) 4135: s = asmstate.sc->func->labtab->lookup(asmtok->ident); 4136: if (!s) 4137: s = asmstate.sc->search(0, asmtok->ident, &scopesym); 4138: if (!s) 4139: { // Assume it is a label, and define that label 4140: s = asmstate.sc->func->searchLabel(asmtok->ident); 4141: } 4142: } 4143: else 4144: s = asmstate.sc->search(0, asmtok->ident, &scopesym); 4145: if (!s) 4146: asmerr(EM_undefined, asmtok->toChars()); 4147: 4148: Identifier *id = asmtok->ident; 4149: asm_token(); 4150: if (tok_value == TOKdot) 4151: { Expression *e; 4152: VarExp *v; 4153: 4154: e = new IdentifierExp(asmstate.loc, id); 4155: while (1) 4156: { 4157: asm_token(); 4158: if (tok_value == TOKidentifier) 4159: { 4160: e = new DotIdExp(asmstate.loc, e, asmtok->ident); 4161: asm_token(); 4162: if (tok_value != TOKdot) 4163: break; 4164: } 4165: else 4166: { 4167: asmerr(EM_ident_exp); 4168: break; 4169: } 4170: } 4171: e = e->semantic(asmstate.sc); 4172: e = e->optimize(WANTvalue | WANTinterpret); 4173: if (e->isConst()) 4174: { 4175: if (e->type->isintegral()) 4176: { 4177: o1->disp = e->toInteger(); 4178: goto Lpost; 4179: } 4180: else if (e->type->isreal()) 4181: { 4182: o1->real = e->toReal(); 4183: o1->ptype = e->type; 4184: goto Lpost; 4185: } 4186: else 4187: { 4188: asmerr(EM_bad_op, e->toChars()); 4189: } 4190: } 4191: else if (e->op == TOKvar) 4192: { 4193: v = (VarExp *)(e); 4194: s = v->var; 4195: } 4196: else 4197: { 4198: asmerr(EM_bad_op, e->toChars()); 4199: } 4200: } 4201: 4202: asm_merge_symbol(o1,s); 4203: 4204: /* This attempts to answer the question: is 4205: * char[8] foo; 4206: * of size 1 or size 8? Presume it is 8 if foo 4207: * is the last token of the operand. 4208: */ 4209: if (o1->ptype && tok_value != TOKcomma && tok_value != TOKeof) 4210: { 4211: for (; 4212: o1->ptype->ty == Tsarray; 4213: o1->ptype = o1->ptype->nextOf()) 4214: { 4215: ; 4216: } 4217: } 4218: 4219: Lpost: 4220: #if 0 4221: // for [] 4222: if (tok_value == TOKlbracket) 4223: o1 = asm_prim_post(o1); 4224: #endif 4225: goto Lret; 4226: } 4227: break; 4228: 4229: case TOKint32v: 4230: case TOKuns32v: 4231: o1 = opnd_calloc(); 4232: o1->disp = asmtok->int32value; 4233: asm_token(); 4234: break; 4235: 4236: case TOKint64v: 4237: case TOKuns64v: 4238: o1 = opnd_calloc(); 4239: o1->disp = asmtok->int64value; 4240: asm_token(); 4241: break; 4242: 4243: case TOKfloat32v: 4244: o1 = opnd_calloc(); 4245: o1->real = asmtok->float80value; 4246: o1->ptype = Type::tfloat32; 4247: asm_token(); 4248: break; 4249: 4250: case TOKfloat64v: 4251: o1 = opnd_calloc(); 4252: o1->real = asmtok->float80value; 4253: o1->ptype = Type::tfloat64; 4254: asm_token(); 4255: break; 4256: 4257: case TOKfloat80v: 4258: o1 = opnd_calloc(); 4259: o1->real = asmtok->float80value; 4260: o1->ptype = Type::tfloat80; 4261: asm_token(); 4262: break; 4263: 4264: case ASMTKlocalsize: 4265: o1 = opnd_calloc(); 4266: o1->s = asmstate.psLocalsize; 4267: o1->ptype = Type::tint32; 4268: asm_token(); 4269: break; 4270: } 4271: Lret: 4272: return o1; 4273: } 4274: 4275: /******************************* 4276: */ 4277: 4278: #if 0 4279: STATIC OPND *asm_prim_post(OPND *o1) 4280: { 4281: OPND *o2; 4282: Declaration *d = o1->s ? o1->s->isDeclaration() : NULL; 4283: Type *t; 4284: 4285: t = d ? d->type : o1->ptype; 4286: while (1) 4287: { 4288: switch (tok_value) 4289: { 4290: #if 0 4291: case TKarrow: 4292: if (++o1->indirect > 1) 4293: { 4294: BAD_OPERAND: 4295: asmerr(EM_bad_operand); 4296: } 4297: if (s->Sclass != SCregister) 4298: goto BAD_OPERAND; 4299: if (!typtr(t->Tty)) 4300: { 4301: asmerr(EM_pointer,t,(type *) NULL); 4302: } 4303: else 4304: t = t->Tnext; 4305: case TKcolcol: 4306: if (tybasic(t->Tty) != TYstruct) 4307: asmerr(EM_not_struct); // not a struct or union type 4308: goto L1; 4309: 4310: case TOKdot: 4311: for (; t && tybasic(t->Tty) != TYstruct; 4312: t = t->Tnext) 4313: ; 4314: if (!t) 4315: asmerr(EM_not_struct); 4316: L1: 4317: /* try to find the symbol */ 4318: asm_token(); 4319: if (tok_value != TOKidentifier) 4320: asmerr(EM_ident_exp); 4321: s = n2_searchmember(t->Ttag,tok.TKid); 4322: if (!s) 4323: { 4324: err_notamember(tok.TKid,t->Ttag); 4325: } 4326: else 4327: { 4328: asm_merge_symbol(o1,s); 4329: t = s->Stype; 4330: asm_token(); 4331: } 4332: break; 4333: #endif 4334: 4335: case TOKlbracket: 4336: asm_token(); 4337: asm_TKlbra_seen++; 4338: o2 = asm_cond_exp(); 4339: asm_chktok(TOKrbracket,EM_rbra); 4340: asm_TKlbra_seen--; 4341: return asm_merge_opnds(o1, o2); 4342: 4343: default: 4344: return o1; 4345: } 4346: } 4347: } 4348: #endif 4349: 4350: /******************************* 4351: */ 4352: 4353: void iasm_term() 4354: { 4355: if (asmstate.bInit) 4356: { 4357: asmstate.psDollar = NULL; 4358: asmstate.psLocalsize = NULL; 4359: asmstate.bInit = 0; 4360: } 4361: } 4362: 4363: /********************************** 4364: * Return mask of registers used by block bp. 4365: */ 4366: 4367: regm_t iasm_regs(block *bp) 4368: { 4369: #ifdef DEBUG 4370: if (debuga) 4371: printf("Block iasm regs = 0x%X\n", bp->usIasmregs); 4372: #endif 4373: 4374: refparam |= bp->bIasmrefparam; 4375: return bp->usIasmregs; 4376: } 4377: 4378: 4379: /************************ AsmStatement ***************************************/ 4380: 4381: Statement *AsmStatement::semantic(Scope *sc) 4382: { 4383: //printf("AsmStatement::semantic()\n"); 4384: 4385: assert(sc->func); 4386: #if DMDV2 4387: if (sc->func->setUnsafe()) 4388: error("inline assembler not allowed in @safe function %s", sc->func->toChars()); 4389: #endif 4390: 4391: OP *o; 4392: OPND *o1 = NULL,*o2 = NULL, *o3 = NULL; 4393: PTRNTAB ptb; 4394: unsigned usNumops; 4395: unsigned char uchPrefix = 0; 4396: unsigned char bAsmseen;
warning C4101: 'bAsmseen' : unreferenced local variable
4397: char *pszLabel = NULL; 4398: code *c;
warning C4101: 'c' : unreferenced local variable
4399: FuncDeclaration *fd = sc->parent->isFuncDeclaration(); 4400: 4401: assert(fd); 4402: 4403: if (!tokens) 4404: return NULL; 4405: 4406: memset(&asmstate, 0, sizeof(asmstate)); 4407: 4408: asmstate.statement = this; 4409: asmstate.sc = sc; 4410: 4411: #if 0 // don't use bReturnax anymore, and will fail anyway if we use return type inference 4412: // Scalar return values will always be in AX. So if it is a scalar 4413: // then asm block sets return value if it modifies AX, if it is non-scalar 4414: // then always assume that the ASM block sets up an appropriate return 4415: // value. 4416: 4417: asmstate.bReturnax = 1; 4418: if (sc->func->type->nextOf()->isscalar()) 4419: asmstate.bReturnax = 0; 4420: #endif 4421: 4422: // Assume assembler code takes care of setting the return value 4423: sc->func->hasReturnExp |= 8; 4424: 4425: if (!asmstate.bInit) 4426: { 4427: asmstate.bInit = TRUE; 4428: init_optab(); 4429: asmstate.psDollar = new LabelDsymbol(Id::__dollar); 4430: //asmstate.psLocalsize = new VarDeclaration(0, Type::tint32, Id::__LOCAL_SIZE, NULL); 4431: asmstate.psLocalsize = new Dsymbol(Id::__LOCAL_SIZE); 4432: cod3_set32(); 4433: } 4434: 4435: asmstate.loc = loc; 4436: 4437: asmtok = tokens; 4438: asm_token_trans(asmtok); 4439: if (setjmp(asmstate.env)) 4440: { asmtok = NULL; // skip rest of line 4441: tok_value = TOKeof; 4442: exit(EXIT_FAILURE); 4443: goto AFTER_EMIT; 4444: } 4445: 4446: switch (tok_value) 4447: { 4448: case ASMTKnaked: 4449: naked = TRUE; 4450: sc->func->naked = TRUE; 4451: asm_token(); 4452: break; 4453: 4454: case ASMTKeven: 4455: asm_token(); 4456: asmalign = 2; 4457: break; 4458: 4459: case TOKalign: 4460: { unsigned align; 4461: 4462: asm_token(); 4463: align = asm_getnum(); 4464: if (ispow2(align) == -1) 4465: asmerr(EM_align, align); // power of 2 expected 4466: else 4467: asmalign = align; 4468: break; 4469: } 4470: 4471: // The following three convert the keywords 'int', 'in', 'out' 4472: // to identifiers, since they are x86 instructions. 4473: case TOKint32: 4474: o = asm_op_lookup(Id::__int->toChars()); 4475: goto Lopcode; 4476: 4477: case TOKin: 4478: o = asm_op_lookup(Id::___in->toChars()); 4479: goto Lopcode; 4480: 4481: case TOKout: 4482: o = asm_op_lookup(Id::___out->toChars()); 4483: goto Lopcode; 4484: 4485: case TOKidentifier: 4486: o = asm_op_lookup(asmtok->ident->toChars()); 4487: if (!o) 4488: goto OPCODE_EXPECTED; 4489: 4490: Lopcode: 4491: asmstate.ucItype = o->usNumops & ITMASK; 4492: asm_token(); 4493: if (o->usNumops > 3) 4494: { 4495: switch (asmstate.ucItype) 4496: { 4497: case ITdata: 4498: asmcode = asm_db_parse(o); 4499: goto AFTER_EMIT; 4500: 4501: case ITaddr: 4502: asmcode = asm_da_parse(o); 4503: goto AFTER_EMIT; 4504: } 4505: } 4506: // get the first part of an expr 4507: o1 = asm_cond_exp(); 4508: if (tok_value == TOKcomma) 4509: { 4510: asm_token(); 4511: o2 = asm_cond_exp(); 4512: } 4513: if (tok_value == TOKcomma) 4514: { 4515: asm_token(); 4516: o3 = asm_cond_exp(); 4517: } 4518: // match opcode and operands in ptrntab to verify legal inst and 4519: // generate 4520: 4521: ptb = asm_classify(o, o1, o2, o3, &usNumops); 4522: assert(ptb.pptb0); 4523: 4524: // 4525: // The Multiply instruction takes 3 operands, but if only 2 are seen 4526: // then the third should be the second and the second should 4527: // be a duplicate of the first. 4528: // 4529: 4530: if (asmstate.ucItype == ITopt && 4531: (usNumops == 2) && 4532: (ASM_GET_aopty(o2->usFlags) == _imm) && 4533: ((o->usNumops & ITSIZE) == 3)) 4534: { 4535: o3 = o2; 4536: o2 = opnd_calloc(); 4537: *o2 = *o1; 4538: 4539: // Re-classify the opcode because the first classification 4540: // assumed 2 operands. 4541: 4542: ptb = asm_classify(o, o1, o2, o3, &usNumops); 4543: } 4544: #if 0 4545: else 4546: if (asmstate.ucItype == ITshift && (ptb.pptb2->usOp2 == 0 || 4547: (ptb.pptb2->usOp2 & _cl))) { 4548: opnd_free(o2); 4549: o2 = NULL; 4550: usNumops = 1; 4551: } 4552: #endif 4553: asmcode = asm_emit(loc, usNumops, ptb, o, o1, o2, o3); 4554: break; 4555: 4556: default: 4557: OPCODE_EXPECTED: 4558: asmerr(EM_opcode_exp, asmtok->toChars()); // assembler opcode expected 4559: break; 4560: } 4561: 4562: AFTER_EMIT: 4563: opnd_free(o1); 4564: opnd_free(o2); 4565: opnd_free(o3); 4566: 4567: if (tok_value != TOKeof) 4568: asmerr(EM_eol); // end of line expected 4569: //return asmstate.bReturnax; 4570: return this; 4571: } 4572: 4573: