Changeset 572
- Timestamp:
- 07/04/10 00:32:30 (2 years ago)
- Files:
-
- branches/dmd-1.x/src/backend/code.h (modified) (1 diff)
- branches/dmd-1.x/src/backend/el.h (modified) (2 diffs)
- branches/dmd-1.x/src/backend/elfobj.c (modified) (8 diffs)
- branches/dmd-1.x/src/backend/iasm.h (modified) (3 diffs)
- branches/dmd-1.x/src/backend/machobj.c (modified) (1 diff)
- branches/dmd-1.x/src/backend/melf.h (modified) (1 diff)
- branches/dmd-1.x/src/backend/out.c (modified) (1 diff)
- branches/dmd-1.x/src/backend/ptrntab.c (modified) (1 diff)
- branches/dmd-1.x/src/iasm.c (modified) (18 diffs)
- trunk/src/backend/code.h (modified) (1 diff)
- trunk/src/backend/el.h (modified) (2 diffs)
- trunk/src/backend/elfobj.c (modified) (8 diffs)
- trunk/src/backend/iasm.h (modified) (3 diffs)
- trunk/src/backend/machobj.c (modified) (1 diff)
- trunk/src/backend/melf.h (modified) (1 diff)
- trunk/src/backend/out.c (modified) (1 diff)
- trunk/src/backend/ptrntab.c (modified) (1 diff)
- trunk/src/iasm.c (modified) (19 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
branches/dmd-1.x/src/backend/code.h
r569 r572 369 369 #define CFjmp16 2 // need 16 bit jump offset (long branch) 370 370 #define CFtarg 4 // this code is the target of a jump 371 371 #define CFseg 8 // get segment of immediate value 372 372 #define CFoff 0x10 // get offset of immediate value 373 373 #define CFss 0x20 // generate an SS: segment override (not with 374 374 // CFes at the same time, though!) 375 375 #define CFpsw 0x40 // we need the flags result after this instruction 376 376 #define CFopsize 0x80 // prefix with operand size 377 377 #define CFaddrsize 0x100 // prefix with address size 378 378 #define CFds 0x200 // need DS override (not with es, ss, or cs ) 379 379 #define CFcs 0x400 // need CS override 380 380 #define CFfs 0x800 // need FS override 381 381 #define CFgs (CFcs | CFfs) // need GS override 382 382 #define CFwait 0x1000 // If I32 it indicates when to output a WAIT 383 383 #define CFselfrel 0x2000 // if self-relative 384 384 #define CFunambig 0x4000 // indicates cannot be accessed by other addressing 385 385 // modes 386 386 #define CFtarg2 0x8000 // like CFtarg, but we can't optimize this away 387 387 #define CFvolatile 0x10000 // volatile reference, do not schedule 388 388 #define CFclassinit 0x20000 // class init code 389 #define CFoffset64 0x40000 // offset is 64 bits 389 390 390 391 #define CFPREFIX (CFSEG | CFopsize | CFaddrsize) 391 392 #define CFSEG (CFes | CFss | CFds | CFcs | CFfs | CFgs) 392 393 393 394 unsigned char Irex; // REX prefix 394 395 395 396 unsigned char Iop; 396 397 unsigned char Irm; // reg/mode 397 398 398 399 unsigned char Iop2; // second opcode byte 399 400 unsigned char Isib; // SIB byte 400 401 401 402 unsigned char Iop3; // third opcode byte 402 403 403 404 unsigned char IFL1,IFL2; // FLavors of 1st, 2nd operands 404 405 union evc IEV1; // 1st operand, if any 405 406 #define IEVpointer1 IEV1._EP.Vpointer 406 407 #define IEVseg1 IEV1._EP.Vseg 407 408 #define IEVsym1 IEV1.sp.Vsym 408 409 #define IEVdsym1 IEV1.dsp.Vsym branches/dmd-1.x/src/backend/el.h
r442 r572 1 1 // Copyright (C) 1985-1995 by Symantec 2 // Copyright (C) 2000-20 09by Digital Mars2 // Copyright (C) 2000-2010 by Digital Mars 3 3 // All Rights Reserved 4 4 // http://www.digitalmars.com 5 5 // Written by Walter Bright 6 6 /* 7 7 * This source file is made available for personal use 8 8 * only. The license is in /dmd/src/dmd/backendlicense.txt 9 9 * or /dm/src/dmd/backendlicense.txt 10 10 * For any other uses, please contact Digital Mars. 11 11 */ 12 12 13 13 /* Routines to handle elems. */ 14 14 15 15 #if __SC__ 16 16 #pragma once 17 17 #endif 18 18 19 19 #ifndef EL_H 20 20 #define EL_H 1 21 21 22 22 #if TARGET_MAC … … 108 108 { 109 109 // Ety2: Must be in same position as Ety! 110 110 tym_t Ety2_; // data type (TYxxxx) 111 111 #define Ety2 _EU._EC.Ety2_ 112 112 unsigned char Ecomsub_; // number of remaining references to 113 113 // this common subexp (used to determine 114 114 // first, intermediate, and last references 115 115 // to a CSE) 116 116 #define Ecomsub _EU._EC.Ecomsub_ 117 117 118 118 #if TARGET_POWERPC 119 119 unsigned char Gflags; 120 120 #define GFLassrval 1 // element is rvalue of an assign 121 121 #define GFLsignok 2 // element does not need sign extend 122 122 #define GFLstrthis_fixed 4 // strthis child elem has been fixed 123 123 // on first pass, do not do it again 124 124 #endif 125 125 }_EC; 126 126 }_EU; 127 127 128 targ_size_t Enumbytes;// number of bytes for type if TYstruct | TYarray128 unsigned Enumbytes; // number of bytes for type if TYstruct | TYarray 129 129 TARGET_structELEM // target specific additions 130 130 Srcpos Esrcpos; // source file position 131 131 }; 132 132 133 133 #define typemask(e) ((!MARS && PARSER) ? (e)->ET->Tty : (e)->Ety ) 134 134 #define typetym(e) ((e)->ET->Tty) 135 135 #define el_fl(e) ((enum FL)((e)->EV.sp.Vsym->Sfl)) 136 136 #define Eoffset EV.sp.Voffset 137 137 #define Esymnum EV.sp.Vsymnum 138 138 139 139 #define list_elem(list) ((elem *) list_ptr(list)) 140 140 #define list_setelem(list,ptr) list_ptr(list) = (elem *)(ptr) 141 141 #define cnst(e) ((e)->Eoper == OPconst) /* Determine if elem is a constant */ 142 142 #define E1 EV.eop.Eleft /* left child */ 143 143 #define E2 EV.eop.Eright /* right child */ 144 144 #define Erd EV.sp.spu.Erd // reaching definition 145 145 146 146 #define el_int(a,b) el_long(a,b) 147 147 148 148 typedef elem *elem_p; /* try to reduce the symbol table size */ branches/dmd-1.x/src/backend/elfobj.c
r569 r572 41 41 //#define DEBSYM 0x7E 42 42 43 43 static Outbuffer *fobjbuf; 44 44 45 45 regm_t BYTEREGS = BYTEREGS_INIT; 46 46 regm_t ALLREGS = ALLREGS_INIT; 47 47 48 48 static char __file__[] = __FILE__; // for tassert.h 49 49 #include "tassert.h" 50 50 51 51 #define MATCH_SECTION 1 52 52 53 53 #define DEST_LEN (IDMAX + IDOHD + 1) 54 54 char *obj_mangle2(Symbol *s,char *dest); 55 55 56 56 #if MARS 57 57 // C++ name mangling is handled by front end 58 58 #define cpp_mangle(s) ((s)->Sident) 59 59 #endif 60 60 61 /*************************************************** 62 * Correspondence of relocation types 63 * 386 32 bit in 64 64 in 64 64 * RI_TYPE_SYM32 R_X86_64_32 R_X86_64_64 65 * RI_TYPE_GOTOFF R_X86_64_PC32 R_X86_64_ 66 * RI_TYPE_GOTPC R_X86_64_ R_X86_64_ 67 * RI_TYPE_GOT32 R_X86_64_ R_X86_64_ 68 * RI_TYPE_TLS_GD R_X86_64_TLSGD R_X86_64_ 69 * RI_TYPE_TLS_IE R_X86_64_GOTTPOFF R_X86_64_ 70 * RI_TYPE_TLS_LE R_X86_64_TPOFF32 R_X86_64_ 71 * RI_TYPE_PLT32 R_X86_64_PLT32 R_X86_64_ 72 * RI_TYPE_PC32 R_X86_64_PC32 R_X86_64_ 73 */ 61 74 62 75 /****************************************** 63 76 */ 64 77 65 78 symbol *GOTsym; // global offset table reference 66 79 67 80 symbol *elfobj_getGOTsym() 68 81 { 69 82 if (!GOTsym) 70 83 { 71 84 GOTsym = symbol_name("_GLOBAL_OFFSET_TABLE_",SCglobal,tspvoid); 72 85 } 73 86 return GOTsym; 74 87 } 75 88 76 89 static void objfile_write(FILE *fd, void *buffer, unsigned len); 77 90 78 91 STATIC char * objmodtoseg (const char *modname); 79 92 STATIC void obj_browse_flush(); 80 93 STATIC void objfixupp (struct FIXUP *); 81 94 STATIC void ledata_new (int seg,targ_size_t offset); 82 static int obj_align(Symbol *s);83 95 void obj_tlssections(); 84 96 85 97 static IDXSYM elf_addsym(IDXSTR sym, targ_size_t val, unsigned sz, 86 98 unsigned typ,unsigned bind,IDXSEC sec); 87 99 static long elf_align(FILE *fd, targ_size_t size, long offset); 88 100 89 101 // The object file is built is several separate pieces 90 102 91 103 // Non-repeatable section types have single output buffers 92 104 // Pre-allocated buffers are defined for: 93 105 // Section Names string table 94 106 // Section Headers table 95 107 // Symbol table 96 108 // String table 97 109 // Notes section 98 110 // Comment data 99 111 100 112 // Section Names - String table for section names only 101 113 static Outbuffer *section_names; 102 114 #define SEC_NAMES_INIT 800 … … 1236 1248 { 1237 1249 //dbg_printf("obj_exestr(char *%s)\n",p); 1238 1250 } 1239 1251 1240 1252 /************************** 1241 1253 * Embed string in obj. 1242 1254 */ 1243 1255 1244 1256 void obj_user(const char *p) 1245 1257 { 1246 1258 //dbg_printf("obj_user(char *%s)\n",p); 1247 1259 } 1248 1260 1249 1261 /******************************* 1250 1262 * Output a weak extern record. 1251 1263 */ 1252 1264 1253 1265 void obj_wkext(Symbol *s1,Symbol *s2) 1254 1266 { 1255 1267 //dbg_printf("obj_wkext(Symbol *%s,Symbol *s2)\n",s1->Sident,s2->Sident); 1256 #if 01257 char buffer[2+2+2];1258 int i;1259 1260 buffer[0] = 0x80;1261 buffer[1] = 0xA8;1262 i = 2;1263 i += insidx(&buffer[2],s1->Sxtrnnum);1264 i += insidx(&buffer[i],s2->Sxtrnnum);1265 objrecord(COMENT,buffer,i);1266 #endif1267 1268 } 1268 1269 1269 1270 /******************************* 1270 1271 * Output file name record. 1271 1272 * 1272 1273 * Currently assumes that obj_filename will not be called 1273 1274 * twice for the same file. 1274 1275 */ 1275 1276 1276 1277 void obj_filename(const char *modname) 1277 { unsigned strtab_idx; 1278 unsigned symtab_idx; 1279 1278 { 1280 1279 //dbg_printf("obj_filename(char *%s)\n",modname); 1281 strtab_idx = elf_addstr(symtab_strings,modname);1280 unsigned strtab_idx = elf_addstr(symtab_strings,modname); 1282 1281 elf_addsym(strtab_idx,0,0,STT_FILE,STB_LOCAL,SHT_ABS); 1283 1282 } 1284 1283 1285 1284 /******************************* 1286 1285 * Embed compiler version in .obj file. 1287 1286 */ 1288 1287 1289 1288 void obj_compiler() 1290 1289 { 1291 1290 //dbg_printf("obj_compiler\n"); 1292 1291 comment_data = new Outbuffer(); 1293 1292 comment_data->write(compiler,sizeof(compiler)); 1294 1293 //dbg_printf("Comment data size %d\n",comment_data->size()); 1295 1294 } 1296 1295 1297 #if 01298 /********************************1299 * Convert module name to code segment name.1300 * Output:1301 * mem_malloc'd code seg name1302 */1303 1304 STATIC char * objmodtoseg(const char *modname)1305 { char *csegname = NULL;1306 1307 if (LARGECODE) // if need to add in module name1308 { int i;1309 char *m;1310 static const char suffix[] = "_TEXT";1311 1312 // Prepend the module name to the beginning of the _TEXT1313 m = filespecgetroot(filespecname(modname));1314 strupr(m);1315 i = strlen(m);1316 csegname = mem_malloc(i + sizeof(suffix));1317 strcpy(csegname,m);1318 strcat(csegname,suffix);1319 mem_free(m);1320 }1321 return csegname;1322 }1323 #endif1324 1296 1325 1297 //#if NEWSTATICDTOR 1326 1298 1327 1299 /************************************** 1328 1300 * Symbol is the function that calls the static constructors. 1329 1301 * Put a pointer to it into a special segment that the startup code 1330 1302 * looks at. 1331 1303 * Input: 1332 1304 * s static constructor function 1333 1305 * dtor !=0 if leave space for static destructor 1334 1306 * seg 1: user 1335 1307 * 2: lib 1336 1308 * 3: compiler 1337 1309 */ 1338 1310 1339 1311 void obj_staticctor(Symbol *s,int dtor,int none) 1340 1312 { 1341 1313 // Static constructors and destructors 1342 1314 IDXSEC seg; 1343 1315 Outbuffer *buf; 1344 1316 1345 1317 //dbg_printf("obj_staticctor(%s) offset %x\n",s->Sident,s->Soffset); 1346 1318 //symbol_print(s); 1347 1319 s->Sseg = seg = 1348 1320 elf_getsegment(".ctors", NULL, SHT_PROGDEF, SHF_ALLOC|SHF_WRITE, 4); 1349 1321 buf = SegData[seg]->SDbuf; 1350 1322 if (I64) 1351 1323 buf->write64(s->Soffset); 1352 1324 else 1353 1325 buf->write32(s->Soffset); 1354 elf_addrel(seg,SegData[seg]->SDoffset, RI_TYPE_SYM32,STI_TEXT,0);1326 elf_addrel(seg,SegData[seg]->SDoffset,I64 ? R_X86_64_64 : RI_TYPE_SYM32,STI_TEXT,0); 1355 1327 SegData[seg]->SDoffset = buf->size(); 1356 1328 } 1357 1329 1358 1330 /************************************** 1359 1331 * Symbol is the function that calls the static destructors. 1360 1332 * Put a pointer to it into a special segment that the exit code 1361 1333 * looks at. 1362 1334 * Input: 1363 1335 * s static destructor function 1364 1336 */ 1365 1337 1366 1338 void obj_staticdtor(Symbol *s) 1367 1339 { 1368 1340 IDXSEC seg; 1369 1341 Outbuffer *buf; 1370 1342 1371 1343 //dbg_printf("obj_staticdtor(%s) offset %x\n",s->Sident,s->Soffset); 1372 1344 //symbol_print(s); 1373 1345 seg = elf_getsegment(".dtors", NULL, SHT_PROGDEF, SHF_ALLOC|SHF_WRITE, 4); 1374 1346 buf = SegData[seg]->SDbuf; 1375 1347 if (I64) 1376 1348 buf->write64(s->Soffset); 1377 1349 else 1378 1350 buf->write32(s->Soffset); 1379 //elf_addrel(seg,0,RI_TYPE_SYM32,STI_TEXT,0); 1380 elf_addrel(seg,SegData[seg]->SDoffset,RI_TYPE_SYM32,s->Sxtrnnum,0); 1351 elf_addrel(seg,SegData[seg]->SDoffset,I64 ? R_X86_64_64 : RI_TYPE_SYM32,s->Sxtrnnum,0); 1381 1352 SegData[seg]->SDoffset = buf->size(); 1382 1353 } 1383 1354 1384 1355 //#else 1385 1356 1386 1357 /*************************************** 1387 1358 * Stuff pointer to function in its own segment. 1388 1359 * Used for static ctor and dtor lists. 1389 1360 */ 1390 1361 1391 1362 void obj_funcptr(Symbol *s) 1392 1363 { 1393 1364 //dbg_printf("obj_funcptr(%s) \n",s->Sident); 1394 1365 } 1395 1366 1396 1367 //#endif 1397 1368 1398 1369 /*************************************** 1399 1370 * Stuff the following data in a separate segment: 1400 1371 * pointer to function 1401 1372 * pointer to ehsym 1402 1373 * length of function 1403 1374 */ 1404 1375 1405 1376 void obj_ehtables(Symbol *sfunc,targ_size_t size,Symbol *ehsym) 1406 1377 { 1407 1378 //dbg_printf("obj_ehtables(%s) \n",sfunc->Sident); 1408 1379 1409 symbol *ehtab_entry; 1410 dt_t **pdte; 1411 1412 ehtab_entry = symbol_generate(SCstatic,type_alloc(TYint)); 1380 symbol *ehtab_entry = symbol_generate(SCstatic,type_alloc(TYint)); 1413 1381 symbol_keep(ehtab_entry); 1414 1382 elf_getsegment(".deh_beg", NULL, SHT_PROGDEF, SHF_ALLOC, 4); 1415 1383 ehtab_entry->Sseg = elf_getsegment(".deh_eh", NULL, SHT_PROGDEF, SHF_ALLOC, 4); 1416 1384 elf_getsegment(".deh_end", NULL, SHT_PROGDEF, SHF_ALLOC, 4); 1417 1385 ehtab_entry->Stype->Tmangle = mTYman_c; 1418 1386 ehsym->Stype->Tmangle = mTYman_c; 1419 pdte = &ehtab_entry->Sdt;1387 dt_t **pdte = &ehtab_entry->Sdt; 1420 1388 pdte = dtxoff(pdte,sfunc,0,TYnptr); 1421 1389 pdte = dtxoff(pdte,ehsym,0,TYnptr); 1422 1390 pdte = dtnbytes(pdte,4,(char *)&sfunc->Ssize); 1423 1391 outdata(ehtab_entry); 1424 1392 } 1425 1393 1426 1394 /********************************************* 1427 1395 * Put out symbols that define the beginning/end of the .deh_eh section. 1428 1396 */ 1429 1397 1430 1398 void obj_ehsections() 1431 { int sec; 1432 IDXSYM symidx; 1433 IDXSTR namidx; 1434 1435 sec = elf_getsegment(".deh_beg", NULL, SHT_PROGDEF, SHF_ALLOC, 4); 1399 { 1400 int sec = elf_getsegment(".deh_beg", NULL, SHT_PROGDEF, SHF_ALLOC, 4); 1436 1401 //obj_bytes(sec, 0, 4, NULL); 1437 1402 1438 namidx = elf_addstr(symtab_strings,"_deh_beg");1403 IDXSTR namidx = elf_addstr(symtab_strings,"_deh_beg"); 1439 1404 elf_addsym(namidx, 0, 0, STT_OBJECT, STB_GLOBAL, MAP_SEG2SECIDX(sec)); 1440 1405 //elf_addsym(namidx, 0, 4, STT_OBJECT, STB_GLOBAL, MAP_SEG2SECIDX(sec)); 1441 1406 1442 1407 elf_getsegment(".deh_eh", NULL, SHT_PROGDEF, SHF_ALLOC, 4); 1443 1408 1444 1409 sec = elf_getsegment(".deh_end", NULL, SHT_PROGDEF, SHF_ALLOC, 4); 1445 1410 namidx = elf_addstr(symtab_strings,"_deh_end"); 1446 1411 elf_addsym(namidx, 0, 0, STT_OBJECT, STB_GLOBAL, MAP_SEG2SECIDX(sec)); 1447 1412 1448 1413 obj_tlssections(); 1449 1414 } 1450 1415 1451 1416 /********************************************* 1452 1417 * Put out symbols that define the beginning/end of the thread local storage sections. 1453 1418 */ 1454 1419 1455 1420 void obj_tlssections() 1456 1421 { 1457 1422 IDXSTR namidx; 1458 1423 … … 1676 1641 * won't be storing D gc roots in their tls. 1677 1642 * Output: 1678 1643 * seg_tlsseg set to segment number for TLS segment. 1679 1644 * Returns: 1680 1645 * segment for TLS segment 1681 1646 */ 1682 1647 1683 1648 seg_data *obj_tlsseg() 1684 1649 { 1685 1650 /* Ensure that ".tdata" precedes any other .tdata. section, as the ld 1686 1651 * linker script fails to work right. 1687 1652 */ 1688 1653 elf_getsegment(".tdata", NULL, SHT_PROGDEF, SHF_ALLOC|SHF_WRITE|SHF_TLS, 4); 1689 1654 1690 1655 static const char tlssegname[] = ".tdata."; 1691 1656 //dbg_printf("obj_tlsseg(\n"); 1692 1657 1693 1658 if (seg_tlsseg == UNKNOWN) 1694 1659 { 1695 1660 seg_tlsseg = elf_getsegment(tlssegname, NULL, SHT_PROGDEF, 1696 SHF_ALLOC|SHF_WRITE|SHF_TLS, 4);1661 SHF_ALLOC|SHF_WRITE|SHF_TLS, I64 ? 16 : 4); 1697 1662 } 1698 1663 return SegData[seg_tlsseg]; 1699 1664 } 1700 1665 1701 1666 1702 1667 /********************************* 1703 1668 * Define segments for Thread Local Storage. 1704 1669 * Output: 1705 1670 * seg_tlsseg_bss set to segment number for TLS segment. 1706 1671 * Returns: 1707 1672 * segment for TLS segment 1708 1673 */ 1709 1674 1710 1675 seg_data *obj_tlsseg_bss() 1711 1676 { 1712 1677 static const char tlssegname[] = ".tbss"; 1713 1678 //dbg_printf("obj_tlsseg_bss(\n"); 1714 1679 1715 1680 if (seg_tlsseg_bss == UNKNOWN) 1716 1681 { 1717 1682 seg_tlsseg_bss = elf_getsegment(tlssegname, NULL, SHT_NOBITS, 1718 SHF_ALLOC|SHF_WRITE|SHF_TLS, 4);1683 SHF_ALLOC|SHF_WRITE|SHF_TLS, I64 ? 16 : 4); 1719 1684 } 1720 1685 return SegData[seg_tlsseg_bss]; 1721 1686 } 1722 1687 1723 1688 1724 1689 /******************************* 1725 1690 * Output an alias definition record. 1726 1691 */ 1727 1692 1728 1693 void obj_alias(const char *n1,const char *n2) 1729 { unsigned len; 1730 char *buffer; 1731 1694 { 1732 1695 dbg_printf("obj_alias(%s,%s)\n",n1,n2); 1733 1696 assert(0); 1734 1697 #if NOT_DONE 1735 buffer = (char *) alloca(strlen(n1) + strlen(n2) + 2 * ONS_OHD);1736 len = obj_namestring(buffer,n1);1698 char *buffer = (char *) alloca(strlen(n1) + strlen(n2) + 2 * ONS_OHD); 1699 unsigned len = obj_namestring(buffer,n1); 1737 1700 len += obj_namestring(buffer + len,n2); 1738 1701 objrecord(ALIAS,buffer,len); 1739 1702 #endif 1740 1703 } 1741 1704 1742 char *unsstr (unsigned value)1743 { 1744 static char buffer [64];1745 1746 sprintf (buffer, "%d", value);1705 char *unsstr(unsigned value) 1706 { 1707 static char buffer[64]; 1708 1709 sprintf(buffer, "%d", value); 1747 1710 return buffer; 1748 1711 } 1749 1712 1750 1713 /******************************* 1751 1714 * Mangle a name. 1752 1715 * Returns: 1753 1716 * mangled name 1754 1717 */ 1755 1718 1756 1719 char *obj_mangle2(Symbol *s,char *dest) 1757 1720 { 1758 size_t len;1759 1721 char *name; 1760 1722 1761 1723 //dbg_printf("obj_mangle('%s'), mangle = x%x\n",s->Sident,type_mangle(s->Stype)); 1762 1724 symbol_debug(s); 1763 1725 assert(dest); 1764 1726 #if SCPP 1765 1727 name = CPP ? cpp_mangle(s) : s->Sident; 1766 1728 #elif MARS 1767 1729 name = cpp_mangle(s); 1768 1730 #else 1769 1731 name = s->Sident; 1770 1732 #endif 1771 len = strlen(name); // # of bytes in name1733 size_t len = strlen(name); // # of bytes in name 1772 1734 //dbg_printf("len %d\n",len); 1773 1735 switch (type_mangle(s->Stype)) 1774 1736 { 1775 1737 case mTYman_pas: // if upper case 1776 1738 case mTYman_for: 1777 1739 if (len >= DEST_LEN) 1778 1740 dest = (char *)mem_malloc(len + 1); 1779 1741 memcpy(dest,name,len + 1); // copy in name and ending 0 1780 1742 for (int i = 0; 1; i++) 1781 1743 { char c = dest[i]; 1782 1744 if (!c) 1783 1745 break; 1784 1746 if (c >= 'a' && c <= 'z') 1785 1747 dest[i] = c + 'A' - 'a'; 1786 1748 } 1787 1749 break; 1788 1750 case mTYman_std: 1789 1751 #if TARGET_LINUX || TARGET_FREEBSD || TARGET_SOLARIS 1790 1752 if (tyfunc(s->ty()) && !variadic(s->Stype)) 1791 1753 #else … … 1815 1777 memcpy(dest,name,len+1);// copy in name and trailing 0 1816 1778 break; 1817 1779 1818 1780 default: 1819 1781 #ifdef DEBUG 1820 1782 printf("mangling %x\n",type_mangle(s->Stype)); 1821 1783 symbol_print(s); 1822 1784 #endif 1823 1785 printf("%d\n", type_mangle(s->Stype)); 1824 1786 assert(0); 1825 1787 } 1826 1788 //dbg_printf("\t %s\n",dest); 1827 1789 return dest; 1828 1790 } 1829 1791 1830 1792 /******************************* 1831 1793 * Export a function name. 1832 1794 */ 1833 1795 1834 1796 void obj_export(Symbol *s,unsigned argsize) 1835 { char *coment; 1836 size_t len; 1837 1797 { 1838 1798 //dbg_printf("obj_export(%s,%d)\n",s->Sident,argsize); 1839 1799 1840 1800 } 1841 1801 1842 1802 /******************************* 1843 1803 * Update data information about symbol 1844 1804 * align for output and assign segment 1845 1805 * if not already specified. 1846 1806 * 1847 1807 * Input: 1848 1808 * sdata data symbol 1849 1809 * datasize output size 1850 1810 * seg default seg if not known 1851 1811 * Returns: 1852 1812 * actual seg 1853 1813 */ 1854 1814 1855 1815 int elf_data_start(Symbol *sdata, targ_size_t datasize, int seg) 1856 1816 { 1857 1817 targ_size_t alignbytes; … … 1985 1944 return symidx; 1986 1945 } 1987 1946 1988 1947 int objextdef(const char *name) 1989 1948 { 1990 1949 return objextern(name); 1991 1950 } 1992 1951 1993 1952 /******************************* 1994 1953 * Output an external for existing symbol. 1995 1954 * Input: 1996 1955 * s Symbol to do EXTDEF on 1997 1956 * (Name is to be mangled) 1998 1957 * Returns: 1999 1958 * Symbol table index of the definition 2000 1959 * NOTE: Numbers will not be linear. 2001 1960 */ 2002 1961 2003 1962 int objextern(Symbol *s) 2004 1963 { 2005 IDXSTR namidx;2006 1964 int symtype,sectype; 2007 targ_size_tsize;1965 unsigned size; 2008 1966 2009 1967 //dbg_printf("objextern('%s') %x\n",s->Sident,s->Svalue); 2010 1968 symbol_debug(s); 2011 namidx = elf_addmangled(s);1969 IDXSTR namidx = elf_addmangled(s); 2012 1970 2013 1971 #if SCPP 2014 1972 if (s->Sscope && !tyfunc(s->ty())) 2015 1973 { 2016 1974 symtype = STT_OBJECT; 2017 1975 sectype = SHT_COMMON; 2018 1976 size = type_size(s->Stype); 2019 1977 } 2020 1978 else 2021 1979 #endif 2022 1980 { 2023 1981 symtype = STT_NOTYPE; 2024 1982 sectype = SHT_UNDEF; 2025 1983 size = 0; 2026 1984 } 2027 1985 if (s->ty() & mTYthread) 2028 1986 { 2029 1987 //printf("objextern('%s') %x TLS\n",s->Sident,s->Svalue); 2030 1988 symtype = STT_TLS; 2031 1989 } … … 2034 1992 /*(s->ty() & mTYweak) ? STB_WEAK : */STB_GLOBAL, sectype); 2035 1993 return s->Sxtrnnum; 2036 1994 2037 1995 } 2038 1996 2039 1997 /******************************* 2040 1998 * Output a common block definition. 2041 1999 * Input: 2042 2000 * p -> external identifier 2043 2001 * size size in bytes of each elem 2044 2002 * count number of elems 2045 2003 * Returns: 2046 2004 * Symbol table index for symbol 2047 2005 */ 2048 2006 2049 2007 int obj_comdef(Symbol *s,targ_size_t size,targ_size_t count) 2050 2008 { 2051 2009 //printf("obj_comdef('%s',%d,%d)\n",s->Sident,size,count); 2052 2010 symbol_debug(s); 2053 2011 2012 int align = I64 ? 16 : 4; 2054 2013 if (s->ty() & mTYthread) 2055 2014 { 2056 2015 s->Sseg = elf_getsegment(".tbss.", cpp_mangle(s), 2057 SHT_NOBITS, SHF_ALLOC|SHF_WRITE|SHF_TLS, 4);2016 SHT_NOBITS, SHF_ALLOC|SHF_WRITE|SHF_TLS, align); 2058 2017 s->Sfl = FLtlsdata; 2059 2018 SegData[s->Sseg]->SDsym = s; 2060 2019 SegData[s->Sseg]->SDoffset += size * count; 2061 2020 objpubdef(s->Sseg, s, 0); 2062 2021 searchfixlist(s); 2063 2022 return s->Sseg; 2064 2023 } 2065 2024 else 2066 2025 { 2067 2026 s->Sseg = elf_getsegment(".bss.", cpp_mangle(s), 2068 SHT_NOBITS, SHF_ALLOC|SHF_WRITE, 4);2027 SHT_NOBITS, SHF_ALLOC|SHF_WRITE, align); 2069 2028 s->Sfl = FLudata; 2070 2029 SegData[s->Sseg]->SDsym = s; 2071 2030 SegData[s->Sseg]->SDoffset += size * count; 2072 2031 objpubdef(s->Sseg, s, 0); 2073 2032 searchfixlist(s); 2074 2033 return s->Sseg; 2075 2034 } 2076 2035 #if 0 2077 2036 IDXSTR namidx = elf_addmangled(s); 2078 2037 alignOffset(UDATA,size); 2079 2038 IDXSYM symidx = elf_addsym(namidx, SegData[UDATA]->SDoffset, size*count, 2080 2039 (s->ty() & mTYthread) ? STT_TLS : STT_OBJECT, 2081 2040 STB_WEAK, SHI_BSS); 2082 2041 //dbg_printf("\tobj_comdef returning symidx %d\n",symidx); 2083 2042 s->Sseg = UDATA; 2084 2043 s->Sfl = FLudata; 2085 2044 SegData[UDATA]->SDoffset += size * count; 2086 2045 return symidx; 2087 2046 #endif 2088 2047 } … … 2345 2304 * reftodatseg(DATA,offset,3 * sizeof(int *),UDATA); 2346 2305 */ 2347 2306 2348 2307 void reftodatseg(int seg,targ_size_t offset,targ_size_t val, 2349 2308 unsigned targetdatum,int flags) 2350 2309 { 2351 2310 Outbuffer *buf; 2352 2311 int save; 2353 2312 2354 2313 buf = SegData[seg]->SDbuf; 2355 2314 save = buf->size(); 2356 2315 buf->setsize(offset); 2357 2316 //dbg_printf("reftodatseg(seg=%d, offset=x%lx, val=x%lx,data %x, flags %x )\n", 2358 2317 // seg,offset,val,targetdatum,flags); 2359 2318 /*if (OPT_IS_SET(OPTfwritable_strings)) 2360 2319 { 2361 2320 elf_addrel(seg,offset,RI_TYPE_SYM32,STI_DATA,0); 2362 2321 } 2363 2322 else*/ 2364 2323 { 2365 unsigned type = RI_TYPE_SYM32; 2366 2367 if (MAP_SEG2TYP(seg) == CODE && config.flags3 & CFG3pic) 2368 type = RI_TYPE_GOTOFF; 2369 else if (MAP_SEG2SEC(targetdatum)->sh_flags & SHF_TLS) 2370 type = config.flags3 & CFG3pic ? RI_TYPE_TLS_GD : RI_TYPE_TLS_LE; 2371 2372 elf_addrel(seg,offset,type,STI_RODAT,0); 2373 } 2374 if (I64) 2375 buf->write64(val); 2376 else 2377 buf->write32(val); 2378 if (save > offset + NPTRSIZE) 2324 int relinfo; 2325 2326 if (I64) 2327 { 2328 if (MAP_SEG2TYP(seg) == CODE && config.flags3 & CFG3pic) 2329 relinfo = R_X86_64_PC32; 2330 else if (MAP_SEG2SEC(targetdatum)->sh_flags & SHF_TLS) 2331 relinfo = config.flags3 & CFG3pic ? R_X86_64_TLSGD : R_X86_64_TPOFF32; 2332 else 2333 relinfo = R_X86_64_32; 2334 } 2335 else 2336 { 2337 if (MAP_SEG2TYP(seg) == CODE && config.flags3 & CFG3pic) 2338 relinfo = RI_TYPE_GOTOFF; 2339 else if (MAP_SEG2SEC(targetdatum)->sh_flags & SHF_TLS) 2340 relinfo = config.flags3 & CFG3pic ? RI_TYPE_TLS_GD : RI_TYPE_TLS_LE; 2341 else 2342 relinfo = RI_TYPE_SYM32; 2343 } 2344 2345 elf_addrel(seg, offset, relinfo, STI_RODAT, 0); 2346 } 2347 buf->write32(val); 2348 if (save > offset + 4) 2379 2349 buf->setsize(save); 2380 2350 } 2381 2351 2382 2352 /******************************* 2383 2353 * Refer to address that is in the code segment. 2384 2354 * Only offsets are output, regardless of the memory model. 2385 2355 * Used to put values in switch address tables. 2386 2356 * Input: 2387 2357 * seg = where the address is going (CODE or DATA) 2388 2358 * offset = offset within seg 2389 2359 * val = displacement from start of this module 2390 2360 */ 2391 2361 2392 2362 void reftocodseg(int seg,targ_size_t offset,targ_size_t val) 2393 2363 { 2394 2364 Outbuffer *buf; 2395 2365 int save; 2396 2366 int segtyp = MAP_SEG2TYP(seg); 2397 2367 2398 2368 //dbg_printf("reftocodseg(seg=%d, offset=x%lx, val=x%lx )\n",seg,offset,val); 2399 2369 assert(seg > 0); // COMDATs not done yet 2400 2370 buf = SegData[seg]->SDbuf; 2401 2371 save = buf->size(); 2402 2372 buf->setsize(offset); 2403 2373 #if 0 2404 2374 if (segtyp == CODE) 2405 2375 { 2406 2376 val = val - funcsym_p->Soffset; 2407 2377 elf_addrel(seg,offset,RI_TYPE_PC32,funcsym_p->Sxtrnnum,0); 2408 2378 } 2409 2379 else 2410 2380 #endif 2411 2381 { 2412 2382 val = val - funcsym_p->Soffset; 2413 elf_addrel(seg,offset,2414 (config.flags3 & CFG3pic) ? RI_TYPE_GOTOFF : RI_TYPE_SYM32,2415 funcsym_p->Sxtrnnum,0);2416 }2417 if (I64)2418 buf->write64(val);2419 else2420 buf->write32(val);2421 if (save > offset + NPTRSIZE)2383 int relinfo; 2384 if (I64) 2385 relinfo = (config.flags3 & CFG3pic) ? R_X86_64_PC32 : R_X86_64_32; 2386 else 2387 relinfo = (config.flags3 & CFG3pic) ? RI_TYPE_GOTOFF : RI_TYPE_SYM32; 2388 elf_addrel(seg,offset, relinfo, funcsym_p->Sxtrnnum, 0); 2389 } 2390 buf->write32(val); 2391 if (save > offset + 4) 2422 2392 buf->setsize(save); 2423 2393 } 2424 2394 2425 2395 /******************************* 2426 2396 * Refer to an identifier. 2427 2397 * Input: 2428 2398 * segtyp = where the address is going (CODE or DATA) 2429 2399 * offset = offset within seg 2430 2400 * s -> Symbol table entry for identifier 2431 2401 * val = displacement from identifier 2432 2402 * flags = CFselfrel: self-relative 2433 2403 * CFseg: get segment 2434 2404 * CFoff: get offset 2405 * CFoffset64: 64 bit fixup 2435 2406 * Returns: 2436 * number of bytes in reference ( 2 or4 or 8)2407 * number of bytes in reference (4 or 8) 2437 2408 */ 2438 2409 2439 2410 int reftoident(int seg, targ_size_t offset, Symbol *s, targ_size_t val, 2440 2411 int flags) 2441 2412 { 2442 2413 tym_t ty; 2443 2414 bool external = TRUE; 2444 2415 Outbuffer *buf; 2445 2416 elf_u32_f32 relinfo,refseg; 2446 2417 int segtyp = MAP_SEG2TYP(seg); 2447 2418 //assert(val == 0); 2419 int retsize = (flags & CFoffset64) ? 8 : 4; 2448 2420 2449 2421 #if 0 2450 2422 dbg_printf("\nreftoident('%s' seg %d, offset x%lx, val x%lx, flags x%x)\n", 2451 2423 s->Sident,seg,offset,val,flags); 2452 2424 dbg_printf("Sseg = %d, Sxtrnnum = %d\n",s->Sseg,s->Sxtrnnum); 2453 2425 symbol_print(s); 2454 2426 #endif 2455 2427 2456 2428 ty = s->ty(); 2457 2429 if (s->Sxtrnnum) 2458 2430 { // identifier is defined somewhere else 2459 2431 if (I64) 2460 2432 { 2461 2433 if (SymbolTable64[s->Sxtrnnum].st_shndx != SHT_UNDEF) 2462 2434 external = FALSE; 2463 2435 } 2464 2436 else 2465 2437 { 2466 2438 if (SymbolTable[s->Sxtrnnum].st_shndx != SHT_UNDEF) 2467 2439 external = FALSE; 2468 2440 } 2469 2441 } 2470 2442 2471 2443 switch (s->Sclass) 2472 2444 { 2473 2445 case SClocstat: 2474 2446 buf = SegData[seg]->SDbuf; 2475 refseg = /*(OPT_IS_SET(OPTfwritable_strings)) ?2476 STI_DATA : */STI_RODAT;2477 relinfo = config.flags3 & CFG3pic ?2478 RI_TYPE_GOTOFF:RI_TYPE_SYM32,STI_RODAT;2479 if (s->Sfl == FLtlsdata)2480 relinfo = config.flags3 & CFG3pic ? RI_TYPE_TLS_GD : RI_TYPE_TLS_LE;2481 elf_addrel(seg,offset,relinfo,refseg,0);2482 2447 if (I64) 2448 { 2449 if (s->Sfl == FLtlsdata) 2450 relinfo = config.flags3 & CFG3pic ? R_X86_64_TLSGD : R_X86_64_TPOFF32; 2451 else 2452 relinfo = config.flags3 & CFG3pic ? R_X86_64_PC32 : R_X86_64_32; 2453 } 2454 else 2455 { 2456 if (s->Sfl == FLtlsdata) 2457 relinfo = config.flags3 & CFG3pic ? RI_TYPE_TLS_GD : RI_TYPE_TLS_LE; 2458 else 2459 relinfo = config.flags3 & CFG3pic ? RI_TYPE_GOTOFF : RI_TYPE_SYM32; 2460 } 2461 if (flags & CFoffset64 && relinfo == R_X86_64_32) 2462 { 2463 relinfo = R_X86_64_64; 2464 } 2465 elf_addrel(seg,offset,relinfo,STI_RODAT,0); 2466 if (retsize == 8) 2483 2467 buf->write64(val + s->Soffset); 2484 2468 else 2485 2469 buf->write32(val + s->Soffset); 2486 2470 break; 2487 2471 2488 2472 case SCcomdat: 2489 2473 case_SCcomdat: 2490 2474 case SCstatic: 2491 2475 #if 0 2492 2476 if ((s->Sflags & SFLthunk) && s->Soffset) 2493 2477 { // A thunk symbol that has be defined 2494 2478 assert(s->Sseg == seg); 2495 2479 val = (s->Soffset+val) - (offset+4); 2496 2480 goto outaddrval; 2497 2481 } 2498 2482 // FALL_THROUGH 2499 2483 #endif 2500 2484 2501 2485 case SCextern: 2502 2486 case SCcomdef: 2503 2487 case_extern: 2504 2488 case SCglobal: 2505 2489 if (!s->Sxtrnnum) 2506 2490 { // not in symbol table yet - class might change 2507 2491 //dbg_printf("\tadding %s to fixlist\n",s->Sident); 2508 2492 addtofixlist(s,offset,seg,val,flags); 2509 return NPTRSIZE;2493 return retsize; 2510 2494 } 2511 2495 else 2512 2496 { 2513 2497 int save; 2514 2498 buf = SegData[seg]->SDbuf; 2515 2499 save = buf->size(); 2516 2500 buf->setsize(offset); 2517 2501 if (flags & CFselfrel) 2518 2502 { // only for function references within code segments 2519 2503 if (!external && // local definition found 2520 2504 s->Sseg == seg && // within same code segment 2521 2505 (!(config.flags3 & CFG3pic) || // not position indp code 2522 2506 s->Sclass == SCstatic)) // or is pic, but declared static 2523 2507 { // Can use PC relative 2524 2508 //dbg_printf("\tdoing PC relative\n"); 2525 val = (s->Soffset+val) - (offset+ NPTRSIZE);2509 val = (s->Soffset+val) - (offset+4); 2526 2510 } 2527 2511 else 2528 2512 { 2529 val = (targ_size_t)- NPTRSIZE;2513 val = (targ_size_t)-4; 2530 2514 //dbg_printf("\tadding relocation\n"); 2515 if (I64) 2516 relinfo = config.flags3 & CFG3pic ? R_X86_64_PLT32 : R_X86_64_PC32; 2517 else 2518 relinfo = config.flags3 & CFG3pic ? RI_TYPE_PLT32 : RI_TYPE_PC32; 2531 2519 elf_addrel(seg,offset, 2532 config.flags3 & CFG3pic ? RI_TYPE_PLT32 : RI_TYPE_PC32,2520 relinfo, 2533 2521 s->Sxtrnnum,0); 2534 2522 } 2535 2523 } 2536 2524 else 2537 2525 { // code to code code to data, data to code, data to data refs 2538 2526 refseg = s->Sxtrnnum; // default to name symbol table entry 2539 2527 if (s->Sclass == SCstatic) 2540 2528 { // offset into .data or .bss seg 2541 2529 refseg = MAP_SEG2SYMIDX(s->Sseg); 2542 2530 // use segment symbol table entry 2543 2531 val += s->Soffset; 2544 2532 if (!(config.flags3 & CFG3pic) || // all static refs from normal code 2545 2533 segtyp == DATA) // or refs from data from posi indp 2546 2534 { 2547 relinfo = RI_TYPE_SYM32;2535 relinfo = I64 ? R_X86_64_32 : RI_TYPE_SYM32; 2548 2536 } 2549 2537 else 2550 2538 { 2551 relinfo = RI_TYPE_GOTOFF;2539 relinfo = I64 ? R_X86_64_PC32 : RI_TYPE_GOTOFF; 2552 2540 } 2553 2541 } 2554 2542 else if (config.flags3 & CFG3pic && s == GOTsym) 2555 2543 { // relocation for Gbl Offset Tab 2556 relinfo = RI_TYPE_GOTPC;2544 relinfo = I64 ? R_X86_64_NONE : RI_TYPE_GOTPC; 2557 2545 } 2558 2546 else if (segtyp == DATA) 2559 { // relocation from with in DATA seg2560 relinfo = RI_TYPE_SYM32;2547 { // relocation from within DATA seg 2548 relinfo = I64 ? R_X86_64_32 : RI_TYPE_SYM32; 2561 2549 } 2562 2550 else 2563 { // relocation from with in CODE seg 2564 relinfo = config.flags3 & CFG3pic ? 2565 RI_TYPE_GOT32 : RI_TYPE_SYM32; 2551 { // relocation from within CODE seg 2552 if (I64) 2553 relinfo = config.flags3 & CFG3pic ? R_X86_64_NONE : R_X86_64_32; 2554 else 2555 relinfo = config.flags3 & CFG3pic ? RI_TYPE_GOT32 : RI_TYPE_SYM32; 2566 2556 } 2567 2557 if ((s->ty() & mTYLINK) & mTYthread) 2568 2558 { 2569 if ( config.flags3 & CFG3pic)2559 if (I64) 2570 2560 { 2571 if (s->Sclass == SCstatic) 2572 relinfo = RI_TYPE_TLS_LE; // TLS_GD? 2561 if (config.flags3 & CFG3pic) 2562 { 2563 if (s->Sclass == SCstatic) 2564 relinfo = R_X86_64_TPOFF32; // TLS_GD? 2565 else 2566 relinfo = R_X86_64_GOTTPOFF; 2567 } 2573 2568 else 2574 relinfo = RI_TYPE_TLS_IE; 2569 { 2570 if (s->Sclass == SCstatic) 2571 relinfo = R_X86_64_TPOFF32; 2572 else 2573 relinfo = R_X86_64_GOTTPOFF; 2574 } 2575 2575 } 2576 2576 else 2577 2577 { 2578 if (s->Sclass == SCstatic) 2579 relinfo = RI_TYPE_TLS_LE; 2578 if (config.flags3 & CFG3pic) 2579 { 2580 if (s->Sclass == SCstatic) 2581 relinfo = RI_TYPE_TLS_LE; // TLS_GD? 2582 else 2583 relinfo = RI_TYPE_TLS_IE; 2584 } 2580 2585 else 2581 relinfo = RI_TYPE_TLS_IE; 2586 { 2587 if (s->Sclass == SCstatic) 2588 relinfo = RI_TYPE_TLS_LE; 2589 else 2590 relinfo = RI_TYPE_TLS_IE; 2591 } 2582 2592 } 2593 } 2594 if (flags & CFoffset64 && relinfo == R_X86_64_32) 2595 { 2596 relinfo = R_X86_64_64; 2583 2597 } 2584 2598 //printf("\t\t************* adding relocation\n"); 2585 2599 elf_addrel(seg,offset,relinfo,refseg,0); 2586 2600 } 2587 2601 outaddrval: 2588 if ( I64)2602 if (retsize == 8) 2589 2603 buf->write64(val); 2590 2604 else 2591 2605 buf->write32(val); 2592 if (save > offset + NPTRSIZE)2606 if (save > offset + retsize) 2593 2607 buf->setsize(save); 2594 2608 } 2595 2609 break; 2596 2610 2597 2611 case SCsinline: 2598 2612 case SCeinline: 2599 2613 printf ("Undefined inline value <<fixme>>\n"); 2600 2614 //warerr(WM_undefined_inline,s->Sident); 2601 2615 case SCinline: 2602 2616 if (tyfunc(ty)) 2603 2617 { 2604 2618 s->Sclass = SCextern; 2605 2619 goto case_extern; 2606 2620 } 2607 2621 else if (config.flags2 & CFG2comdat) 2608 2622 goto case_SCcomdat; // treat as initialized common block 2609 2623 2610 2624 default: 2611 2625 #ifdef DEBUG 2612 2626 //symbol_print(s); 2613 2627 #endif 2614 2628 assert(0); 2615 2629 } 2616 return NPTRSIZE;2630 return retsize; 2617 2631 } 2618 2632 2619 2633 /***************************************** 2620 2634 * Generate far16 thunk. 2621 2635 * Input: 2622 2636 * s Symbol to generate a thunk for 2623 2637 */ 2624 2638 2625 2639 void obj_far16thunk(Symbol *s) 2626 2640 { 2627 2641 //dbg_printf("obj_far16thunk('%s')\n", s->Sident); 2628 2642 assert(0); 2629 2643 } 2630 2644 2631 2645 /************************************** 2632 2646 * Mark object file as using floating point. 2633 2647 */ 2634 2648 2635 2649 void obj_fltused() 2636 2650 { 2637 2651 //dbg_printf("obj_fltused()\n"); 2638 }2639 2640 static int obj_align(Symbol *s)2641 {2642 if (type_size(s->Stype) == CHARSIZE)2643 return 1;2644 else if (type_size(s->Stype) == SHORTSIZE)2645 return 2;2646 else if (type_size(s->Stype) == LONGSIZE)2647 return 4;2648 else2649 return I64 ? 8 : 4;2650 2652 } 2651 2653 2652 2654 /************************************ 2653 2655 * Close and delete .OBJ file. 2654 2656 */ 2655 2657 2656 2658 void objfile_delete() 2657 2659 { 2658 2660 //remove(fobjname); // delete corrupt output file 2659 2661 } 2660 2662 2661 2663 /********************************** 2662 2664 * Terminate. 2663 2665 */ 2664 2666 2665 2667 void objfile_term() 2666 2668 { 2667 2669 #if TERMCODE 2668 2670 mem_free(fobjname); 2669 2671 fobjname = NULL; … … 2699 2701 offset = (foffset + 31) & ~31; 2700 2702 break; 2701 2703 default: 2702 2704 dbg_printf("size was %d\n",(int)size); 2703 2705 assert(0); 2704 2706 break; 2705 2707 } 2706 2708 if (offset > foffset) 2707 2709 fobjbuf->writezeros(offset - foffset); 2708 2710 return offset; 2709 2711 } 2710 2712 2711 2713 /*************************************** 2712 2714 * Stuff pointer to ModuleInfo in its own segment. 2713 2715 */ 2714 2716 2715 2717 #if MARS 2716 2718 2717 2719 void obj_moduleinfo(Symbol *scc) 2718 2720 { 2719 int offset, codeOffset, refOffset; 2720 Outbuffer *buf; 2721 int seg; 2722 2723 /* Put in the ModuleInfo reference for some reason. */ 2724 /*{ 2725 seg = DATA; 2726 offset = SegData[seg]->SDoffset; 2727 SegData[seg]->SDoffset += reftoident(seg, offset, scc, 0, CFoff); 2728 }*/ 2721 int codeOffset, refOffset; 2729 2722 2730 2723 /* Put in the ModuleReference. */ 2731 2724 { 2732 2725 /* struct ModuleReference 2733 2726 * { 2734 2727 * void* next; 2735 2728 * ModuleReference* module; 2736 2729 * } 2737 2730 */ 2738 seg = DATA; 2731 const int seg = DATA; 2732 alignOffset(seg, NPTRSIZE); 2739 2733 SegData[seg]->SDoffset = SegData[seg]->SDbuf->size(); 2740 2734 refOffset = SegData[seg]->SDoffset; 2741 2735 SegData[seg]->SDbuf->writezeros(NPTRSIZE); 2742 2736 SegData[seg]->SDoffset += NPTRSIZE; 2743 2737 SegData[seg]->SDoffset += reftoident(seg, SegData[seg]->SDoffset, scc, 0, CFoff); 2744 } 2745 2746 /* Constructor that links the ModuleReference into the code. */ 2738 alignOffset(seg, NPTRSIZE); 2739 } 2740 2741 /* Constructor that links the ModuleReference to the head of 2742 * the list pointed to by _Dmoduleref 2743 */ 2747 2744 { 2748 2745 /* ret 2746 * codeOffset: 2749 2747 * pushad 2750 2748 * mov EAX,&ModuleReference 2751 2749 * mov ECX,_DmoduleRef 2752 2750 * mov EDX,[ECX] 2753 2751 * mov [EAX],EDX 2754 2752 * mov [ECX],EAX 2755 2753 * popad 2756 2754 * ret 2757 2755 */ 2758 2756 2759 seg = CODE; 2760 buf = SegData[seg]->SDbuf; 2757 const int reltype = I64 ? R_X86_64_32 : RI_TYPE_SYM32; 2758 const int refsize = 4; // use 32 bit relocations, even in 64 bit mode 2759 2760 const int seg = CODE; 2761 Outbuffer *buf = SegData[seg]->SDbuf; 2761 2762 SegData[seg]->SDoffset = buf->size(); 2762 2763 codeOffset = SegData[seg]->SDoffset + 1; 2763 // codeOffset = SegData[seg]->SDoffset;2764 2764 buf->writeByte(0xC3); /* ret */ 2765 2765 2766 2766 buf->writeByte(0x60); /* pushad */ 2767 2767 2768 2768 /* movl ModuleReference*, %eax */ 2769 2769 buf->writeByte(0xB8); 2770 2770 buf->write32(refOffset); 2771 elf_addrel(seg, codeOffset + 2, RI_TYPE_SYM32, STI_DATA, 0);2771 elf_addrel(seg, codeOffset + 2, reltype, STI_DATA, 0); 2772 2772 2773 2773 /* movl _Dmodule_ref, %ecx */ 2774 2774 buf->writeByte(0xB9); 2775 buf->write32(0); //offset);2776 elf_addrel(seg, codeOffset + 7, RI_TYPE_SYM32, objextern("_Dmodule_ref"), 0);2775 buf->write32(0); 2776 elf_addrel(seg, codeOffset + 7, reltype, objextern("_Dmodule_ref"), 0); 2777 2777 2778 2778 buf->writeByte(0x8B); buf->writeByte(0x11); /* movl (%ecx), %edx */ 2779 2779 buf->writeByte(0x89); buf->writeByte(0x10); /* movl %edx, (%eax) */ 2780 2780 buf->writeByte(0x89); buf->writeByte(0x01); /* movl %eax, (%ecx) */ 2781 2781 2782 2782 buf->writeByte(0x61); /* popad */ 2783 2783 buf->writeByte(0xC3); /* ret */ 2784 2784 SegData[seg]->SDoffset = buf->size(); 2785 2785 } 2786 2786 2787 /* Create the linked list-generating code. */ 2788 seg = elf_getsegment(".ctors", NULL, SHT_PROGDEF, SHF_ALLOC|SHF_WRITE,4); 2789 2790 buf = SegData[seg]->SDbuf; 2787 /* Add reference to constructor into ".ctors" segment 2788 */ 2789 const int seg = elf_getsegment(".ctors", NULL, SHT_PROGDEF, SHF_ALLOC|SHF_WRITE, NPTRSIZE); 2790 2791 Outbuffer *buf = SegData[seg]->SDbuf; 2791 2792 buf->write32(codeOffset); 2792 elf_addrel(seg, SegData[seg]->SDoffset, RI_TYPE_SYM32, STI_TEXT, 0);2793 elf_addrel(seg, SegData[seg]->SDoffset, I64 ? R_X86_64_64 : RI_TYPE_SYM32, STI_TEXT, 0); 2793 2794 SegData[seg]->SDoffset += NPTRSIZE; 2794 2795 } 2795 2796 2796 2797 #endif 2797 2798 /************************************2799 * Output long word of data.2800 * Input:2801 * seg CODE, DATA, CDATA, UDATA2802 * offset offset of start of data2803 * data long word of data2804 * Present only if size == 2:2805 * lcfd LCxxxx | FDxxxx2806 * if (FD_F2 | FD_T6)2807 * idx1 = external Symbol #2808 * else2809 * idx1 = frame datum2810 * idx2 = target datum2811 */2812 2813 void obj_long(int seg,targ_size_t offset,unsigned long data,2814 unsigned lcfd,unsigned idx1,unsigned idx2)2815 {2816 printf ("obj_long\n");2817 exit (1);2818 /*2819 unsigned i;2820 2821 if (2822 (seg != obj.ledata->lseg || // or segments don't match2823 obj.ledata->i + tysize[TYfptr] > LEDATAMAX || // or it'll overflow2824 offset < obj.ledata->offset || // underflow2825 offset > obj.ledata->offset + obj.ledata->i2826 )2827 )2828 ledata_new(seg,offset);2829 i = offset - obj.ledata->offset;2830 if (obj.ledata->i < i + tysize[TYfptr])2831 obj.ledata->i = i + tysize[TYfptr];2832 TOLONG(obj.ledata->data + i,data);2833 if (I32) // if 6 byte far pointers2834 TOWORD(obj.ledata->data + i + LONGSIZE,0); // fill out seg2835 addfixup(offset - obj.ledata->offset,lcfd,idx1,idx2);2836 */2837 }2838 2798 2839 2799 /************************************* 2840 2800 */ 2841 2801 2842 2802 void elfobj_gotref(symbol *s) 2843 2803 { 2844 2804 //printf("elfobj_gotref(%x '%s', %d)\n",s,s->Sident, s->Sclass); 2845 2805 switch(s->Sclass) 2846 2806 { 2847 2807 case SCstatic: 2848 2808 case SClocstat: 2849 2809 s->Sfl = FLgotoff; 2850 2810 break; 2851 2811 2852 2812 case SCextern: 2853 2813 case SCglobal: 2854 2814 case SCcomdat: 2855 2815 case SCcomdef: 2856 2816 s->Sfl = FLgot; 2857 2817 break; branches/dmd-1.x/src/backend/iasm.h
r428 r572 1 1 2 2 /* 3 3 * Copyright (c) 1992-1999 by Symantec 4 * Copyright (c) 1999-20 08by Digital Mars4 * Copyright (c) 1999-2010 by Digital Mars 5 5 * All Rights Reserved 6 6 * http://www.digitalmars.com 7 7 * Written by Mike Cote, John Micco and Walter Bright 8 8 * 9 9 * This source file is made available for personal use 10 10 * only. The license is in /dmd/src/dmd/backendlicense.txt 11 11 * or /dm/src/dmd/backendlicense.txt 12 12 * For any other uses, please contact Digital Mars. 13 13 */ 14 14 15 15 #include <setjmp.h> 16 16 17 17 ///////////////////////////////////////////////// 18 18 // Instruction flags (usFlags) 19 19 // 20 20 // 21 21 22 22 // This is for when the reg field of modregrm specifies which instruction it is 23 23 #define NUM_MASK 0x7 24 24 #define _0 (0x0 | _modrm) // insure that some _modrm bit is set … … 28 28 #define _4 0x4 29 29 #define _5 0x5 30 30 #define _6 0x6 31 31 #define _7 0x7 32 32 33 33 #define _modrm 0x10 34 34 35 35 #define _r _modrm 36 36 #define _cb _modrm 37 37 #define _cw _modrm 38 38 #define _cd _modrm 39 39 #define _cp _modrm 40 40 #define _ib 0 41 41 #define _iw 0 42 42 #define _id 0 43 43 #define _rb 0 44 44 #define _rw 0 45 45 #define _rd 0 46 46 #define _16_bit 0x20 47 47 #define _32_bit 0x40 48 #define _64_bit 0x10000 48 49 #define _I386 0x80 // opcode is only for 386 and later 49 50 #define _16_bit_addr 0x100 50 51 #define _32_bit_addr 0x200 51 52 #define _fwait 0x400 // Add an FWAIT prior to the instruction opcode 52 53 #define _nfwait 0x800 // Do not add an FWAIT prior to the instruction 53 54 54 55 #define MOD_MASK 0xF000 // Mod mask 55 56 #define _modsi 0x1000 // Instruction modifies SI 56 57 #define _moddx 0x2000 // Instruction modifies DX 57 58 #define _mod2 0x3000 // Instruction modifies second operand 58 59 #define _modax 0x4000 // Instruction modifies AX 59 60 #define _modnot1 0x5000 // Instruction does not modify first operand 60 61 #define _modaxdx 0x6000 // instruction modifies AX and DX 61 62 #define _moddi 0x7000 // Instruction modifies DI 62 63 #define _modsidi 0x8000 // Instruction modifies SI and DI 63 64 #define _modcx 0x9000 // Instruction modifies CX 64 65 #define _modes 0xa000 // Instruction modifies ES 65 66 #define _modall 0xb000 // Instruction modifies all register values 66 67 #define _modsiax 0xc000 // Instruction modifies AX and SI 67 68 #define _modsinot1 0xd000 // Instruction modifies SI and not first param 68 69 69 70 ///////////////////////////////////////////////// 70 71 // Operand flags - usOp1, usOp2, usOp3 71 72 // 72 73 73 typedef unsigned shortopflag_t;74 typedef unsigned opflag_t; 74 75 75 76 // Operand flags for normal opcodes 76 77 77 78 #define _r8 CONSTRUCT_FLAGS( _8, _reg, _normal, 0 ) 78 79 #define _r16 CONSTRUCT_FLAGS(_16, _reg, _normal, 0 ) 79 80 #define _r32 CONSTRUCT_FLAGS(_32, _reg, _normal, 0 ) 81 #define _r64 CONSTRUCT_FLAGS(_64, _reg, _normal, 0 ) 80 82 #define _m8 CONSTRUCT_FLAGS(_8, _m, _normal, 0 ) 81 83 #define _m16 CONSTRUCT_FLAGS(_16, _m, _normal, 0 ) 82 84 #define _m32 CONSTRUCT_FLAGS(_32, _m, _normal, 0 ) 83 85 #define _m48 CONSTRUCT_FLAGS( _48, _m, _normal, 0 ) 84 #define _m64 CONSTRUCT_FLAGS( _ anysize, _m, _normal, 0 )86 #define _m64 CONSTRUCT_FLAGS( _64, _m, _normal, 0 ) 85 87 #define _m128 CONSTRUCT_FLAGS( _anysize, _m, _normal, 0 ) 86 88 #define _rm8 CONSTRUCT_FLAGS(_8, _rm, _normal, 0 ) 87 89 #define _rm16 CONSTRUCT_FLAGS(_16, _rm, _normal, 0 ) 88 90 #define _rm32 CONSTRUCT_FLAGS(_32, _rm, _normal, 0) 89 91 #define _r32m16 CONSTRUCT_FLAGS(_32|_16, _rm, _normal, 0) 90 92 #define _imm8 CONSTRUCT_FLAGS(_8, _imm, _normal, 0 ) 91 93 #define _imm16 CONSTRUCT_FLAGS(_16, _imm, _normal, 0) 92 94 #define _imm32 CONSTRUCT_FLAGS(_32, _imm, _normal, 0) 93 95 #define _rel8 CONSTRUCT_FLAGS(_8, _rel, _normal, 0) 94 96 #define _rel16 CONSTRUCT_FLAGS(_16, _rel, _normal, 0) 95 97 #define _rel32 CONSTRUCT_FLAGS(_32, _rel, _normal, 0) 96 98 #define _p1616 CONSTRUCT_FLAGS(_32, _p, _normal, 0) 97 99 #define _m1616 CONSTRUCT_FLAGS(_32, _mnoi, _normal, 0) 98 100 #define _p1632 CONSTRUCT_FLAGS(_48, _p, _normal, 0 ) 99 101 #define _m1632 CONSTRUCT_FLAGS(_48, _mnoi, _normal, 0) 100 102 #define _special CONSTRUCT_FLAGS( 0, 0, _rspecial, 0 ) 101 103 #define _seg CONSTRUCT_FLAGS( 0, 0, _rseg, 0 ) 102 104 #define _a16 CONSTRUCT_FLAGS( 0, 0, _addr16, 0 ) 103 105 #define _a32 CONSTRUCT_FLAGS( 0, 0, _addr32, 0 ) 104 106 #define _f16 CONSTRUCT_FLAGS( 0, 0, _fn16, 0) 105 107 // Near function pointer 106 108 #define _f32 CONSTRUCT_FLAGS( 0, 0, _fn32, 0) 107 109 // Far function pointer 108 110 #define _lbl CONSTRUCT_FLAGS( 0, 0, _flbl, 0 ) 109 111 // Label (in current function) 110 112 111 113 #define _mmm32 CONSTRUCT_FLAGS( 0, _m, 0, _32) 112 #define _mmm64 CONSTRUCT_FLAGS( 0, _m, 0, _64)113 #define _mmm128 CONSTRUCT_FLAGS( 0, _m, 0, _ 128)114 #define _mmm64 CONSTRUCT_FLAGS( _64, _m, 0, _f64) 115 #define _mmm128 CONSTRUCT_FLAGS( 0, _m, 0, _f128) 114 116 115 117 #define _xmm_m32 CONSTRUCT_FLAGS( _32, _m, _rspecial, 0) 116 118 #define _xmm_m64 CONSTRUCT_FLAGS( _anysize, _m, _rspecial, 0) 117 119 #define _xmm_m128 CONSTRUCT_FLAGS( _anysize, _m, _rspecial, 0) 118 120 119 121 #define _moffs8 (_rel8) 120 122 #define _moffs16 (_rel16 ) 121 123 #define _moffs32 (_rel32 ) 122 124 123 125 124 126 //////////////////////////////////////////////////////////////////// 125 127 // Operand flags for floating point opcodes are all just aliases for 126 128 // normal opcode variants and only asm_determine_operator_flags should 127 129 // need to care. 128 130 // 129 #define _fm80 CONSTRUCT_FLAGS( 0, _m, 0, _ 80 )130 #define _fm64 CONSTRUCT_FLAGS( 0, _m, 0, _ 64 )131 #define _fm128 CONSTRUCT_FLAGS( 0, _m, 0, _ 128 )132 #define _fanysize (_ 64 | _80 | _112 | _224)131 #define _fm80 CONSTRUCT_FLAGS( 0, _m, 0, _f80 ) 132 #define _fm64 CONSTRUCT_FLAGS( 0, _m, 0, _f64 ) 133 #define _fm128 CONSTRUCT_FLAGS( 0, _m, 0, _f128 ) 134 #define _fanysize (_f64 | _f80 | _f112 ) 133 135 134 136 #define _float_m CONSTRUCT_FLAGS( _anysize, _float, 0, _fanysize) 135 137 136 138 #define _st CONSTRUCT_FLAGS( 0, _float, 0, _rst ) // stack register 0 137 #define _m112 CONSTRUCT_FLAGS( 0, _m, 0, _ 112 )138 #define _m224 CONSTRUCT_FLAGS( 0, _m, 0, _224 )139 #define _m112 CONSTRUCT_FLAGS( 0, _m, 0, _f112 ) 140 #define _m224 _m112 139 141 #define _m512 _m224 140 142 #define _sti CONSTRUCT_FLAGS( 0, _float, 0, _rsti ) 141 143 142 144 ////////////////// FLAGS ///////////////////////////////////// 143 145 146 #if 1 147 // bit size 5 3 3 7 148 #define CONSTRUCT_FLAGS( uSizemask, aopty, amod, uRegmask ) \ 149 ( (uSizemask) | (aopty) << 5 | (amod) << 8 | (uRegmask) << 11) 150 151 #define ASM_GET_uSizemask(us) ((us) & 0x1F) 152 #define ASM_GET_aopty(us) ((ASM_OPERAND_TYPE)(((us) >> 5) & 7)) 153 #define ASM_GET_amod(us) ((ASM_MODIFIERS)(((us) >> 8) & 7)) 154 #define ASM_GET_uRegmask(us) (((us) >> 11) & 0x7F) 155 #else 144 156 #define CONSTRUCT_FLAGS( uSizemask, aopty, amod, uRegmask ) \ 145 157 ( (uSizemask) | (aopty) << 4 | (amod) << 7 | (uRegmask) << 10) 146 158 147 159 #define ASM_GET_uSizemask(us) ((us) & 0x0F) 148 160 #define ASM_GET_aopty(us) ((ASM_OPERAND_TYPE)(((us) & 0x70) >> 4)) 149 161 #define ASM_GET_amod(us) ((ASM_MODIFIERS)(((us) & 0x380) >> 7)) 150 162 #define ASM_GET_uRegmask(us) (((us) & 0xFC00) >> 10) 151 152 153 // For uSizemask ( 4bits)163 #endif 164 165 // For uSizemask (5 bits) 154 166 #define _8 0x1 155 167 #define _16 0x2 156 168 #define _32 0x4 157 169 #define _48 0x8 158 #define _anysize (_8 | _16 | _32 | _48 ) 170 #define _64 0x10 171 #define _anysize (_8 | _16 | _32 | _48 | _64 ) 159 172 160 173 // For aopty (3 bits) 161 174 enum ASM_OPERAND_TYPE { 162 175 _reg, // _r8, _r16, _r32 163 176 _m, // _m8, _m16, _m32, _m48 164 177 _imm, // _imm8, _imm16, _imm32 165 178 _rel, // _rel8, _rel16, _rel32 166 179 _mnoi, // _m1616, _m1632 167 180 _p, // _p1616, _p1632 168 181 _rm, // _rm8, _rm16, _rm32 169 182 _float // Floating point operand, look at cRegmask for the 170 183 // actual size 171 184 }; 172 185 173 186 // For amod (3 bits) 174 187 enum ASM_MODIFIERS { 175 188 _normal, // Normal register value 176 189 _rseg, // Segment registers 177 190 _rspecial, // Special registers 178 191 _addr16, // 16 bit address 179 192 _addr32, // 32 bit address 180 193 _fn16, // 16 bit function call 181 194 _fn32, // 32 bit function call 182 195 _flbl // Label 183 196 }; 184 197 185 // For uRegmask ( 6bits)198 // For uRegmask (7 bits) 186 199 187 200 // uRegmask flags when aopty == _float 188 201 #define _rst 0x1 189 202 #define _rsti 0x2 190 #define _64 0x4 191 #define _80 0x8 192 #define _128 0x40 193 #define _112 0x10 194 #define _224 0x20 203 #define _f64 0x4 204 #define _f80 0x8 205 #define _f112 0x10 206 #define _f128 0x20 195 207 196 208 // _seg register values (amod == _rseg) 197 209 // 198 210 #define _ds CONSTRUCT_FLAGS( 0, 0, _rseg, 0x01 ) 199 211 #define _es CONSTRUCT_FLAGS( 0, 0, _rseg, 0x02 ) 200 212 #define _ss CONSTRUCT_FLAGS( 0, 0, _rseg, 0x04 ) 201 213 #define _fs CONSTRUCT_FLAGS( 0, 0, _rseg, 0x08 ) 202 214 #define _gs CONSTRUCT_FLAGS( 0, 0, _rseg, 0x10 ) 203 215 #define _cs CONSTRUCT_FLAGS( 0, 0, _rseg, 0x20 ) 204 216 205 217 // 206 218 // _special register values 207 219 // 208 220 #define _crn CONSTRUCT_FLAGS( 0, 0, _rspecial, 0x01 ) // CRn register (0,2,3) 209 221 #define _drn CONSTRUCT_FLAGS( 0, 0, _rspecial, 0x02 ) // DRn register (0-3,6-7) 210 222 #define _trn CONSTRUCT_FLAGS( 0, 0, _rspecial, 0x04 ) // TRn register (3-7) 211 223 #define _mm CONSTRUCT_FLAGS( 0, 0, _rspecial, 0x08 ) // MMn register (0-7) 212 224 #define _xmm CONSTRUCT_FLAGS( 0, 0, _rspecial, 0x10 ) // XMMn register (0-7) 213 225 214 226 // 215 227 // Default register values 216 228 // 217 229 218 230 #define _al CONSTRUCT_FLAGS( 0, 0, _normal, 0x01 ) // AL register 219 231 #define _ax CONSTRUCT_FLAGS( 0, 0, _normal, 0x02 ) // AX register 220 232 #define _eax CONSTRUCT_FLAGS( 0, 0, _normal, 0x04 ) // EAX register 221 233 #define _dx CONSTRUCT_FLAGS( 0, 0, _normal, 0x08 ) // DX register 222 234 #define _cl CONSTRUCT_FLAGS( 0, 0, _normal, 0x10 ) // CL register 235 #define _rax CONSTRUCT_FLAGS( 0, 0, _normal, 0x40 ) // RAX register 236 223 237 224 238 #define _rplus_r 0x20 225 239 #define _plus_r CONSTRUCT_FLAGS( 0, 0, 0, _rplus_r ) 226 240 // Add the register to the opcode (no mod r/m) 227 241 228 242 229 243 230 244 ////////////////////////////////////////////////////////////////// 231 245 232 246 #define ITprefix 0x10 // special prefix 233 247 #define ITjump 0x20 // jump instructions CALL, Jxx and LOOPxx 234 248 #define ITimmed 0x30 // value of an immediate operand controls 235 249 // code generation 236 250 #define ITopt 0x40 // not all operands are required 237 251 #define ITshift 0x50 // rotate and shift instructions 238 252 #define ITfloat 0x60 // floating point coprocessor instructions 239 253 #define ITdata 0x70 // DB, DW, DD, DQ, DT pseudo-ops 240 254 #define ITaddr 0x80 // DA (define addresss) pseudo-op 241 255 #define ITMASK 0xF0 242 256 #define ITSIZE 0x0F // mask for size … … 266 280 // Float types 267 281 OPdf, 268 282 OPdd, 269 283 OPde, 270 284 271 285 // Deprecated 272 286 OPdw = OPds, 273 287 OPdq = OPdl, 274 288 OPdt = OPde, 275 289 #endif 276 290 }; 277 291 278 292 279 293 /* from iasm.c */ 280 294 int asm_state(int iFlags); 281 295 282 296 void asm_process_fixup( block **ppblockLabels ); 283 297 284 298 typedef struct _PTRNTAB3 { 285 299 unsigned usOpcode; 286 unsigned shortusFlags;300 unsigned usFlags; 287 301 opflag_t usOp1; 288 302 opflag_t usOp2; 289 303 opflag_t usOp3; 290 304 } PTRNTAB3, * PPTRNTAB3, ** PPPTRNTAB3; 291 305 292 306 typedef struct _PTRNTAB2 { 293 307 unsigned usOpcode; 294 unsigned shortusFlags;308 unsigned usFlags; 295 309 opflag_t usOp1; 296 310 opflag_t usOp2; 297 311 } PTRNTAB2, * PPTRNTAB2, ** PPPTRNTAB2; 298 312 299 313 typedef struct _PTRNTAB1 { 300 314 unsigned usOpcode; 301 unsigned shortusFlags;315 unsigned usFlags; 302 316 opflag_t usOp1; 303 317 } PTRNTAB1, * PPTRNTAB1, ** PPPTRNTAB1; 304 318 305 319 typedef struct _PTRNTAB0 { 306 320 unsigned usOpcode; 307 321 #define ASM_END 0xffff // special opcode meaning end of table 308 unsigned shortusFlags;322 unsigned usFlags; 309 323 } PTRNTAB0, * PPTRNTAB0, ** PPPTRNTAB0; 310 324 311 325 typedef union _PTRNTAB { 312 326 PTRNTAB0 *pptb0; 313 327 PTRNTAB1 *pptb1; 314 328 PTRNTAB2 *pptb2; 315 329 PTRNTAB3 *pptb3; 316 330 } PTRNTAB, * PPTRNTAB, ** PPPTRNTAB; 317 331 318 332 typedef struct 319 333 { 320 334 unsigned char usNumops; 321 335 PTRNTAB ptb; 322 336 } OP; 323 337 branches/dmd-1.x/src/backend/machobj.c
r557 r572 2309 2309 int seg = mach_getsegment("__minfodata", "__DATA", align, S_REGULAR); 2310 2310 //printf("obj_moduleinfo(%s) seg = %d:x%x\n", scc->Sident, seg, Offset(seg)); 2311 2311 2312 2312 #if 0 2313 2313 type *t = type_fake(TYint); 2314 2314 t->Tmangle = mTYman_c; 2315 2315 char *p = (char *)malloc(5 + strlen(scc->Sident) + 1); 2316 2316 strcpy(p, "SUPER"); 2317 2317 strcpy(p + 5, scc->Sident); 2318 2318 symbol *s_minfo_beg = symbol_name(p, SCglobal, t); 2319 2319 objpubdef(seg, s_minfo_beg, 0); 2320 2320 #endif 2321 2321 2322 2322 SegData[seg]->SDoffset += reftoident(seg, Offset(seg), scc, 0, CFoff); 2323 2323 2324 2324 mach_getsegment("__minfo_end", "__DATA", align, S_COALESCED, 4); 2325 2325 } 2326 2326 2327 2327 #endif 2328 2328 2329 /************************************2330 * Output long word of data.2331 * Input:2332 * seg CODE, DATA, CDATA, UDATA2333 * offset offset of start of data2334 * data long word of data2335 * Present only if size == 2:2336 * lcfd LCxxxx | FDxxxx2337 * if (FD_F2 | FD_T6)2338 * idx1 = external Symbol #2339 * else2340 * idx1 = frame datum2341 * idx2 = target datum2342 */2343 2344 void obj_long(int seg,targ_size_t offset,unsigned long data,2345 unsigned lcfd,unsigned idx1,unsigned idx2)2346 {2347 printf("obj_long\n");2348 exit(1);2349 }2350 2351 2329 /************************************* 2352 2330 */ 2353 2331 2354 2332 void elfobj_gotref(symbol *s) 2355 2333 { 2356 2334 //printf("elfobj_gotref(%x '%s', %d)\n",s,s->Sident, s->Sclass); 2357 2335 switch(s->Sclass) 2358 2336 { 2359 2337 case SCstatic: 2360 2338 case SClocstat: 2361 2339 s->Sfl = FLgotoff; 2362 2340 break; 2363 2341 2364 2342 case SCextern: 2365 2343 case SCglobal: 2366 2344 case SCcomdat: 2367 2345 case SCcomdef: 2368 2346 s->Sfl = FLgot; 2369 2347 break; 2370 2348 branches/dmd-1.x/src/backend/melf.h
r428 r572 324 324 } Elf64_Phdr; 325 325 326 326 typedef struct { 327 327 Elf64_Word st_name; 328 328 unsigned char st_info; 329 329 unsigned char st_other; 330 330 Elf64_Half st_shndx; 331 331 Elf64_Addr st_value; 332 332 Elf64_Xword st_size; 333 333 } Elf64_Sym; 334 334 335 335 typedef struct { 336 336 Elf64_Addr r_offset; 337 337 Elf64_Xword r_info; 338 338 #define ELF64_R_SYM(i) ((Elf64_Word)((i)>>32)) 339 339 #define ELF64_R_TYPE(i) ((Elf64_Word)(i & 0xFFFFFFFF)) 340 340 #define ELF64_R_INFO(s,t) ((((Elf64_Xword)(s))<<32)|(Elf64_Word)(t)) 341 341 342 342 // X86-64 Relocation types 343 343 344 #define R_X86_64_NONE 0 345 #define R_X86_64_64 1 346 #define R_X86_64_PC32 2 347 #define R_X86_64_GOT32 3 348 #define R_X86_64_PLT32 4 349 #define R_X86_64_COPY 5 350 #define R_X86_64_GLOB_DAT 6 351 #define R_X86_64_JUMP_SLOT 7 352 #define R_X86_64_RELATIVE 8 353 #define R_X86_64_GOTPCREL 9 354 #define R_X86_64_32 10 355 #define R_X86_64_32S 11 356 #define R_X86_64_16 12 357 #define R_X86_64_PC16 13 358 #define R_X86_64_8 14 359 #define R_X86_64_PC8 15 360 #define R_X86_64_DTPMOD64 16 361 #define R_X86_64_DTPOFF64 17 362 #define R_X86_64_TPOFF64 18 363 #define R_X86_64_TLSGD 19 364 #define R_X86_64_TLSLD 20 365 #define R_X86_64_DTPOFF32 21 366 #define R_X86_64_GOTTPOFF 22 367 #define R_X86_64_TPOFF32 23 368 #define R_X86_64_GNU_VTINHERIT 250 369 #define R_X86_64_GNU_VTENTRY 251 344 #define R_X86_64_NONE 0 // -- No relocation 345 #define R_X86_64_64 1 // 64 Direct 64 bit 346 #define R_X86_64_PC32 2 // 32 PC relative 32 bit signed 347 #define R_X86_64_GOT32 3 // 32 32 bit GOT entry 348 #define R_X86_64_PLT32 4 // 32 bit PLT address 349 #define R_X86_64_COPY 5 // -- Copy symbol at runtime 350 #define R_X86_64_GLOB_DAT 6 // 64 Create GOT entry 351 #define R_X86_64_JUMP_SLOT 7 // 64 Create PLT entry 352 #define R_X86_64_RELATIVE 8 // 64 Adjust by program base 353 #define R_X86_64_GOTPCREL 9 // 32 32 bit signed pc relative offset to GOT 354 #define R_X86_64_32 10 // 32 Direct 32 bit zero extended 355 #define R_X86_64_32S 11 // 32 Direct 32 bit sign extended 356 #define R_X86_64_16 12 // 16 Direct 16 bit zero extended 357 #define R_X86_64_PC16 13 // 16 16 bit sign extended pc relative 358 #define R_X86_64_8 14 // 8 Direct 8 bit sign extended 359 #define R_X86_64_PC8 15 // 8 8 bit sign extended pc relative 360 #define R_X86_64_DTPMOD64 16 // 64 ID of module containing symbol 361 #define R_X86_64_DTPOFF64 17 // 64 Offset in TLS block 362 #define R_X86_64_TPOFF64 18 // 64 Offset in initial TLS block 363 #define R_X86_64_TLSGD 19 // 32 PC relative offset to GD GOT block 364 #define R_X86_64_TLSLD 20 // 32 PC relative offset to LD GOT block 365 #define R_X86_64_DTPOFF32 21 // 32 Offset in TLS block 366 #define R_X86_64_GOTTPOFF 22 // 32 PC relative offset to IE GOT entry 367 #define R_X86_64_TPOFF32 23 // 32 Offset in initial TLS block 368 #define R_X86_64_PC64 24 // 64 369 #define R_X86_64_GOTOFF64 25 // 64 370 #define R_X86_64_GOTPC32 26 // 32 371 #define R_X86_64_GNU_VTINHERIT 250 // GNU C++ hack 372 #define R_X86_64_GNU_VTENTRY 251 // GNU C++ hack 370 373 } Elf64_Rel; 371 374 372 375 typedef struct { 373 376 Elf64_Addr r_offset; 374 377 Elf64_Xword r_info; 375 378 Elf64_Sxword r_addend; 376 379 } Elf64_Rela; 377 380 378 381 branches/dmd-1.x/src/backend/out.c
r493 r572 416 416 reftodatseg(seg,offset,dt->DTabytes,DATA,flags); 417 417 else 418 418 reftofarseg(seg,offset,dt->DTabytes,dt->DTseg,flags); 419 419 #endif 420 420 offset += size(dt->Dty); 421 421 break; 422 422 case DT_ibytes: 423 423 obj_bytes(seg,offset,dt->DTn,dt->DTdata); 424 424 offset += dt->DTn; 425 425 break; 426 426 case DT_nbytes: 427 427 obj_bytes(seg,offset,dt->DTnbytes,dt->DTpbytes); 428 428 offset += dt->DTnbytes; 429 429 break; 430 430 case DT_azeros: 431 431 //printf("obj_lidata(seg = %d, offset = %d, azeros = %d)\n", seg, offset, dt->DTazeros); 432 432 obj_lidata(seg,offset,dt->DTazeros); 433 433 offset += dt->DTazeros; 434 434 break; 435 435 case DT_xoff: 436 { symbol *sb; 437 438 sb = dt->DTsym; // get external symbol pointer 436 { 437 symbol *sb = dt->DTsym; // get external symbol pointer 439 438 a = dt->DToffset; // offset from it 440 439 if (tyreg(dt->Dty)) 441 440 flags = CFoff; 442 441 else 443 442 flags = CFoff | CFseg; 443 if (I64) 444 flags |= CFoffset64; 444 445 offset += reftoident(seg,offset,sb,a,flags); 445 446 break; 446 447 } 447 448 case DT_coff: 448 449 reftocodseg(seg,offset,dt->DToffset); 449 450 offset += intsize; 450 451 break; 451 452 case DT_1byte: 452 453 obj_byte(seg,offset++,dt->DTonebyte); 453 454 break; 454 455 default: 455 456 #ifdef DEBUG 456 457 dbg_printf("dt = %p, dt = %d\n",dt,dt->dt); 457 458 #endif 458 459 assert(0); 459 460 } 460 461 } 461 462 #if ELFOBJ || MACHOBJ 462 463 Offset(seg) = offset; 463 464 #else branches/dmd-1.x/src/backend/ptrntab.c
r428 r572 826 826 PTRNTAB2 aptb2IDIV[] = /* IDIV */ { 827 827 { 0xf6, _7, _al, _rm8 }, 828 828 { 0xf7, _7|_16_bit|_moddx, _ax, _rm16 }, 829 829 { 0xf7, _7|_32_bit|_moddx, _eax, _rm32 }, 830 830 { 0xf6, _7 | _modax, _rm8, 0 }, 831 831 { 0xf7, _7|_16_bit|_modaxdx, _rm16, 0 }, 832 832 { 0xf7, _7|_32_bit|_modaxdx, _rm32, 0 }, 833 833 { ASM_END, 0, 0, 0 } 834 834 }; 835 835 PTRNTAB2 aptb2IN[] = /* IN */ { 836 836 { 0xe4, _ib, _al, _imm8 }, 837 837 { 0xe5, _ib|_16_bit,_ax, _imm8 }, 838 838 { 0xe5, _ib|_32_bit,_eax, _imm8 }, 839 839 { 0xec, 0, _al, _dx }, 840 840 { 0xed, _16_bit, _ax, _dx }, 841 841 { 0xed, _32_bit, _eax, _dx }, 842 842 { ASM_END, 0, 0, 0 } 843 843 }; 844 844 PTRNTAB2 aptb2INS[] = /* INS */ { 845 845 { 0x6c, _modsi, _rm8, _dx }, 846 { 0x6d, _modsi|_16_bit, _rm16 | _16_bit, _dx },847 { 0x6d, _32_bit|_modsi, _rm32 | _32_bit, _dx },846 { 0x6d, _modsi|_16_bit, _rm16, _dx }, 847 { 0x6d, _32_bit|_modsi, _rm32, _dx }, 848 848 { ASM_END, 0, 0, 0 } 849 849 }; 850 850 851 851 PTRNTAB2 aptb2LAR[] = /* LAR */ { 852 852 { 0x0f02, _r|_16_bit, _r16, _rm16 }, 853 853 { 0x0f02, _r|_32_bit, _r32, _rm32 }, 854 854 { ASM_END, 0, 0, 0 } 855 855 }; 856 856 PTRNTAB2 aptb2LDS[] = /* LDS */ { 857 857 { 0xc5, _r|_16_bit, _r16, _m32 }, 858 858 { 0xc5, _r|_32_bit, _r32, _m48 }, 859 859 { ASM_END, 0, 0, 0 } 860 860 }; 861 861 862 862 PTRNTAB2 aptb2LEA[] = /* LEA */ { 863 863 { 0x8d, _r|_16_bit, _r16, _m8 | _m16 | _m32 | _m48 }, 864 864 { 0x8d, _r|_32_bit, _r32, _m8 | _m16 | _m32 | _m48 }, 865 865 { 0x8d, _r|_16_bit, _r16, _rel16 }, 866 866 { 0x8d, _r|_32_bit, _r32, _rel32 }, 867 867 { ASM_END, 0, 0, 0 } branches/dmd-1.x/src/iasm.c
r487 r572 1 1 2 2 /* 3 3 * Copyright (c) 1992-1999 by Symantec 4 * Copyright (c) 1999-20 09by Digital Mars4 * Copyright (c) 1999-2010 by Digital Mars 5 5 * All Rights Reserved 6 6 * http://www.digitalmars.com 7 7 * Written by Mike Cote, John Micco and Walter Bright 8 8 * D version by Walter Bright 9 9 * 10 10 * This source file is made available for personal use 11 11 * only. The license is in /dmd/src/dmd/backendlicense.txt 12 12 * For any other uses, please contact Digital Mars. 13 13 */ 14 14 15 15 // Inline assembler for the D programming language compiler 16 16 17 17 #include <ctype.h> 18 18 #include <stdlib.h> 19 19 #include <stdio.h> 20 20 #include <string.h> 21 21 #include <time.h> 22 22 #include <assert.h> 23 23 #include <setjmp.h> 24 24 #if __DMC__ 25 25 #undef setjmp 26 26 #include <limits.h> 27 27 #endif 28 28 29 29 30 30 // D compiler 31 31 #include "mars.h" 32 32 #include "lexer.h" 33 33 #include "mtype.h" 34 34 #include "statement.h" 35 35 #include "id.h" 36 36 #include "declaration.h" 37 37 #include "scope.h" 38 38 #include "init.h" 39 39 #include "enum.h" 40 #include "module.h" 40 41 41 42 // C/C++ compiler 42 43 #define SCOPE_H 1 // avoid conflicts with D's Scope 43 44 #include "cc.h" 44 45 #include "token.h" 45 46 #include "parser.h" 46 47 #include "global.h" 47 48 #include "el.h" 48 49 #include "type.h" 49 50 #include "oper.h" 50 51 #include "code.h" 51 52 #include "iasm.h" 52 53 #include "cpp.h" 53 54 54 55 #undef _DH 55 56 56 57 // I32 isn't set correctly yet because this is the front end, and I32 57 58 // is a backend flag 59 #undef I16 58 60 #undef I32 61 #undef I64 62 #define I16 0 59 63 #define I32 (global.params.isX86_64 == 0) 64 #define I64 (global.params.isX86_64 == 1) 60 65 61 66 //#define EXTRA_DEBUG 1 62 67 63 68 #undef ADDFWAIT 64 69 #define ADDFWAIT() 0 65 70 66 71 // Error numbers 67 72 enum ASMERRMSGS 68 73 { 69 74 EM_bad_float_op, 70 75 EM_bad_addr_mode, 71 76 EM_align, 72 77 EM_opcode_exp, 73 78 EM_prefix, 74 79 EM_eol, 75 80 EM_bad_operand, 76 81 EM_bad_integral_operand, 77 82 EM_ident_exp, 78 83 EM_not_struct, 79 84 EM_nops_expected, … … 289 294 "TR6", 6, _special | _trn, 290 295 "TR7", 7, _special | _trn, 291 296 "MM0", 0, _mm, 292 297 "MM1", 1, _mm, 293 298 "MM2", 2, _mm, 294 299 "MM3", 3, _mm, 295 300 "MM4", 4, _mm, 296 301 "MM5", 5, _mm, 297 302 "MM6", 6, _mm, 298 303 "MM7", 7, _mm, 299 304 "XMM0", 0, _xmm, 300 305 "XMM1", 1, _xmm, 301 306 "XMM2", 2, _xmm, 302 307 "XMM3", 3, _xmm, 303 308 "XMM4", 4, _xmm, 304 309 "XMM5", 5, _xmm, 305 310 "XMM6", 6, _xmm, 306 311 "XMM7", 7, _xmm, 307 312 }; 308 313 314 // 64 bit only registers 315 #define _RAX 0 316 #define _RBX 3 317 #define _RCX 1 318 #define _RDX 2 319 #define _RSI 6 320 #define _RDI 7 321 #define _RBP 5 322 #define _RSP 4 323 #define _R8 8 324 #define _R9 9 325 #define _R10 10 326 #define _R11 11 327 #define _R12 12 328 #define _R13 13 329 #define _R14 14 330 #define _R15 15 331 332 #define _R8D 8 333 #define _R9D 9 334 #define _R10D 10 335 #define _R11D 11 336 #define _R12D 12 337 #define _R13D 13 338 #define _R14D 14 339 #define _R15D 15 340 341 #define _R8W 8 342 #define _R9W 9 343 #define _R10W 10 344 #define _R11W 11 345 #define _R12W 12 346 #define _R13W 13 347 #define _R14W 13 348 #define _R15W 15 349 350 #define _SIL 6 351 #define _DIL 7 352 #define _BPL 5 353 #define _SPL 4 354 #define _R8B 8 355 #define _R9B 9 356 #define _R10B 10 357 #define _R11B 11 358 #define _R12B 12 359 #define _R13B 13 360 #define _R14B 14 361 #define _R15B 15 362 363 static REG regtab64[] = 364 { 365 "RAX", _RAX, _r64 | _rax, 366 "RBX", _RBX, _r64, 367 "RCX", _RCX, _r64, 368 "RDX", _RDX, _r64, 369 "RSI", _RSI, _r64, 370 "RDI", _RDI, _r64, 371 "RBP", _RBP, _r64, 372 "RSP", _RSP, _r64, 373 "R8", _R8, _r64, 374 "R9", _R9, _r64, 375 "R10", _R10, _r64, 376 "R11", _R11, _r64, 377 "R12", _R12, _r64, 378 "R13", _R13, _r64, 379 "R14", _R14, _r64, 380 "R15", _R15, _r64, 381 382 "R8D", _R8D, _r32, 383 "R9D", _R9D, _r32, 384 "R10D", _R10D, _r32, 385 "R11D", _R11D, _r32, 386 "R12D", _R12D, _r32, 387 "R13D", _R13D, _r32, 388 "R14D", _R14D, _r32, 389 "R15D", _R15D, _r32, 390 391 "R8W", _R8W, _r16, 392 "R9W", _R9W, _r16, 393 "R10W", _R10W, _r16, 394 "R11W", _R11W, _r16, 395 "R12W", _R12W, _r16, 396 "R13W", _R13W, _r16, 397 "R14W", _R14W, _r16, 398 "R15W", _R15W, _r16, 399 400 "SIL", _SIL, _r8, 401 "DIL", _DIL, _r8, 402 "BPL", _BPL, _r8, 403 "SPL", _SPL, _r8, 404 "R8B", _R8B, _r8, 405 "R9B", _R9B, _r8, 406 "R10B", _R10B, _r8, 407 "R11B", _R11B, _r8, 408 "R12B", _R12B, _r8, 409 "R13B", _R13B, _r8, 410 "R14B", _R14B, _r8, 411 "R15B", _R15B, _r8, 412 413 "XMM8", 8, _xmm, 414 "XMM9", 9, _xmm, 415 "XMM10", 10, _xmm, 416 "XMM11", 11, _xmm, 417 "XMM12", 12, _xmm, 418 "XMM13", 13, _xmm, 419 "XMM14", 14, _xmm, 420 "XMM15", 15, _xmm, 421 }; 422 309 423 typedef enum { 310 424 ASM_JUMPTYPE_UNSPECIFIED, 311 425 ASM_JUMPTYPE_SHORT, 312 426 ASM_JUMPTYPE_NEAR, 313 427 ASM_JUMPTYPE_FAR 314 428 } ASM_JUMPTYPE; // ajt 315 429 316 430 typedef struct opnd 317 431 { 318 432 REG *base; // if plain register 319 433 REG *pregDisp1; // if [register1] 320 434 REG *pregDisp2; 321 435 REG *segreg; // if segment override 322 436 char indirect; // if had a '*' or '->' 323 437 char bOffset; // if 'offset' keyword 324 438 char bSeg; // if 'segment' keyword 325 439 char bPtr; // if 'ptr' keyword 326 440 unsigned uchMultiplier; // register multiplier; valid values are 0,1,2,4,8 327 441 opflag_t usFlags; 328 442 Dsymbol *s; … … 351 465 int asm_getnum(); 352 466 353 467 STATIC void asmerr(char *, ...); 354 468 STATIC void asmerr(int, ...); 355 469 #pragma SC noreturn(asmerr) 356 470 357 471 STATIC OPND *asm_equal_exp(); 358 472 STATIC OPND *asm_inc_or_exp(); 359 473 STATIC OPND *asm_log_and_exp(); 360 474 STATIC OPND *asm_log_or_exp(); 361 475 STATIC char asm_length_type_size(OPND *popnd); 362 476 STATIC void asm_token(); 363 477 STATIC void asm_token_trans(Token *tok); 364 478 STATIC unsigned char asm_match_flags(opflag_t usOp , opflag_t usTable ); 365 479 STATIC unsigned char asm_match_float_flags(opflag_t usOp, opflag_t usTable); 366 480 STATIC void asm_make_modrm_byte( 367 481 #ifdef DEBUG 368 482 unsigned char *puchOpcode, unsigned *pusIdx, 369 483 #endif 370 484 code *pc, 371 unsigned shortusFlags,485 unsigned usFlags, 372 486 OPND *popnd, OPND *popnd2); 373 487 STATIC regm_t asm_modify_regs(PTRNTAB ptb, OPND *popnd1, OPND *popnd2); 374 488 STATIC void asm_output_flags(opflag_t usFlags); 375 489 STATIC void asm_output_popnd(OPND *popnd); 376 490 STATIC unsigned asm_type_size(Type * ptype); 377 491 STATIC opflag_t asm_float_type_size(Type * ptype, opflag_t *pusFloat); 378 492 STATIC OPND *asm_mul_exp(); 379 493 STATIC OPND *asm_br_exp(); 380 494 STATIC OPND *asm_primary_exp(); 381 495 STATIC OPND *asm_prim_post(OPND *); 382 496 STATIC OPND *asm_rel_exp(); 383 497 STATIC OPND *asm_shift_exp(); 384 498 STATIC OPND *asm_una_exp(); 385 499 STATIC OPND *asm_xor_exp(); 386 500 STATIC void *link_alloc(size_t, void *); 387 501 STATIC void asm_chktok(enum TOK toknum, unsigned errnum); 388 502 STATIC code *asm_db_parse(OP *pop); 389 503 STATIC code *asm_da_parse(OP *pop); 390 504 391 unsigned shortcompute_hashkey(char *);505 unsigned compute_hashkey(char *); 392 506 393 507 394 508 /******************************* 395 509 */ 396 510 397 511 STATIC OPND *opnd_calloc() 398 512 { OPND *o; 399 513 400 514 o = new OPND(); 401 515 memset(o, 0, sizeof(*o)); 402 516 return o; 403 517 } 404 518 405 519 /******************************* 406 520 */ 407 521 408 522 STATIC void opnd_free(OPND *o) 409 523 { 410 524 if (o) 411 525 { … … 461 575 { 462 576 popnd2->usFlags = usFlags2 = asm_determine_operand_flags(popnd2); 463 577 if (!popnd3) 464 578 usNumops = 2; 465 579 else 466 580 { 467 581 popnd3->usFlags = usFlags3 = asm_determine_operand_flags(popnd3); 468 582 usNumops = 3; 469 583 } 470 584 } 471 585 } 472 586 473 587 // Now check to insure that the number of operands is correct 474 588 usActual = (pop->usNumops & ITSIZE); 475 589 if (usActual != usNumops && asmstate.ucItype != ITopt && 476 590 asmstate.ucItype != ITfloat) 477 591 { 478 592 PARAM_ERROR: 479 593 asmerr(EM_nops_expected, usActual, asm_opstr(pop), usNumops); 480 594 } 481 *pusNumops = usNumops; 595 *pusNumops = asmstate.ucItype == ITfloat ? usActual : usNumops; 596 if (usActual < usNumops) 597 *pusNumops = usActual; 598 else 599 *pusNumops = usNumops; 482 600 // 483 601 // The number of arguments matches, now check to find the opcode 484 602 // in the associated opcode table 485 603 // 486 604 RETRY: 487 605 //printf("usActual = %d\n", usActual); 488 606 switch (usActual) 489 607 { 490 608 case 0: 491 609 ptbRet = pop->ptb ; 492 610 goto RETURN_IT; 493 611 494 612 case 1: 495 613 //printf("usFlags1 = "); asm_output_flags(usFlags1); printf("\n"); 496 614 for (pptb1 = pop->ptb.pptb1; pptb1->usOpcode != ASM_END; 497 615 pptb1++) 498 616 { 499 617 //printf("table = "); asm_output_flags(pptb1->usOp1); printf("\n"); 500 618 bMatch1 = asm_match_flags(usFlags1, pptb1->usOp1); 619 //printf("bMatch1 = x%x\n", bMatch1); 501 620 if (bMatch1) 502 621 { if (pptb1->usOpcode == 0x68 && 503 I32&&622 !I16 && 504 623 pptb1->usOp1 == _imm16 505 624 ) 506 625 // Don't match PUSH imm16 in 32 bit code 507 626 continue; 508 627 break; 509 628 } 510 629 if ((asmstate.ucItype == ITimmed) && 511 630 asm_match_flags(usFlags1, 512 631 CONSTRUCT_FLAGS(_8 | _16 | _32, _imm, _normal, 513 632 0)) && 514 633 popnd1->disp == pptb1->usFlags) 515 634 break; 516 635 if ((asmstate.ucItype == ITopt || 517 636 asmstate.ucItype == ITfloat) && 518 637 !usNumops && 519 638 !pptb1->usOp1) 520 639 { 521 640 if (usNumops > 1) 522 641 goto PARAM_ERROR; 523 642 break; … … 785 904 } 786 905 if (popnd->pregDisp1 && !popnd->base) 787 906 { 788 907 us = asm_float_type_size(popnd->ptype, &usFloat); 789 908 //printf("us = x%x, usFloat = x%x\n", us, usFloat); 790 909 if (popnd->pregDisp1->ty & _r32) 791 910 return(CONSTRUCT_FLAGS(us, _m, _addr32, usFloat)); 792 911 else 793 912 if (popnd->pregDisp1->ty & _r16) 794 913 return(CONSTRUCT_FLAGS(us, _m, _addr16, usFloat)); 795 914 } 796 915 else if (popnd->s != 0) 797 916 { 798 917 us = asm_float_type_size(popnd->ptype, &usFloat); 799 918 return CONSTRUCT_FLAGS(us, _m, _normal, usFloat); 800 919 } 801 920 802 921 if (popnd->segreg) 803 922 { 804 923 us = asm_float_type_size(popnd->ptype, &usFloat); 805 if (I32) 924 if (I16) 925 return(CONSTRUCT_FLAGS(us, _m, _addr16, usFloat)); 926 else 806 927 return(CONSTRUCT_FLAGS(us, _m, _addr32, usFloat)); 807 else808 return(CONSTRUCT_FLAGS(us, _m, _addr16, usFloat));809 928 } 810 929 811 930 #if 0 812 931 if (popnd->real) 813 932 { 814 933 switch (popnd->ptype->ty) 815 934 { 816 935 case Tfloat32: 817 936 popnd->s = fconst(popnd->real); 818 937 return(CONSTRUCT_FLAGS(_32, _m, _normal, 0)); 819 938 820 939 case Tfloat64: 821 940 popnd->s = dconst(popnd->real); 822 return(CONSTRUCT_FLAGS(0, _m, _normal, _ 64));941 return(CONSTRUCT_FLAGS(0, _m, _normal, _f64)); 823 942 824 943 case Tfloat80: 825 944 popnd->s = ldconst(popnd->real); 826 return(CONSTRUCT_FLAGS(0, _m, _normal, _ 80));945 return(CONSTRUCT_FLAGS(0, _m, _normal, _f80)); 827 946 } 828 947 } 829 948 #endif 830 949 831 950 asmerr(EM_bad_float_op); // unknown operand for floating point instruction 832 951 return 0; 833 952 } 834 953 835 954 /******************************* 836 955 */ 837 956 838 957 STATIC opflag_t asm_determine_operand_flags(OPND *popnd) 839 958 { 840 959 Dsymbol *ps; 841 960 int ty; 842 961 opflag_t us; 843 962 opflag_t sz; 844 963 ASM_OPERAND_TYPE opty; 845 964 ASM_MODIFIERS amod; 846 965 … … 850 969 851 970 if (asmstate.ucItype == ITfloat) 852 971 return asm_determine_float_flags(popnd); 853 972 854 973 // If just a register 855 974 if (popnd->base && !popnd->s && !popnd->disp && !popnd->real) 856 975 return popnd->base->ty; 857 976 #if DEBUG 858 977 if (debuga) 859 978 printf("popnd->base = %s\n, popnd->pregDisp1 = %p\n", popnd->base ? popnd->base->regstr : "NONE", popnd->pregDisp1); 860 979 #endif 861 980 ps = popnd->s; 862 981 Declaration *ds = ps ? ps->isDeclaration() : NULL; 863 982 if (ds && ds->storage_class & STClazy) 864 983 sz = _anysize; 865 984 else 866 985 sz = asm_type_size((ds && ds->storage_class & (STCout | STCref)) ? popnd->ptype->pointerTo() : popnd->ptype); 867 986 if (popnd->pregDisp1 && !popnd->base) 868 987 { 869 988 if (ps && ps->isLabel() && sz == _anysize) 870 sz = I 32 ? _32 : _16;989 sz = I16 ? _16 : _32; 871 990 return (popnd->pregDisp1->ty & _r32) 872 991 ? CONSTRUCT_FLAGS(sz, _m, _addr32, 0) 873 992 : CONSTRUCT_FLAGS(sz, _m, _addr16, 0); 874 993 } 875 994 else if (ps) 876 995 { 877 996 if (popnd->bOffset || popnd->bSeg || ps == asmstate.psLocalsize) 878 return I 32879 ? CONSTRUCT_FLAGS(_ 32, _imm, _normal, 0)880 : CONSTRUCT_FLAGS(_ 16, _imm, _normal, 0);997 return I16 998 ? CONSTRUCT_FLAGS(_16, _imm, _normal, 0) 999 : CONSTRUCT_FLAGS(_32, _imm, _normal, 0); 881 1000 882 1001 if (ps->isLabel()) 883 1002 { 884 1003 switch (popnd->ajt) 885 1004 { 886 1005 case ASM_JUMPTYPE_UNSPECIFIED: 887 1006 if (ps == asmstate.psDollar) 888 1007 { 889 1008 if (popnd->disp >= CHAR_MIN && 890 1009 popnd->disp <= CHAR_MAX) 891 1010 us = CONSTRUCT_FLAGS(_8, _rel, _flbl,0); 892 1011 else 893 1012 if (popnd->disp >= SHRT_MIN && 894 1013 popnd->disp <= SHRT_MAX) 895 1014 us = CONSTRUCT_FLAGS(_16, _rel, _flbl,0); 896 1015 else 897 1016 us = CONSTRUCT_FLAGS(_32, _rel, _flbl,0); 898 1017 } 899 1018 else if (asmstate.ucItype != ITjump) 900 1019 { if (sz == _8) 901 1020 { us = CONSTRUCT_FLAGS(_8,_rel,_flbl,0); 902 1021 break; 903 1022 } 904 1023 goto case_near; 905 1024 } 906 1025 else 907 us = I 32908 ? CONSTRUCT_FLAGS(_8|_ 32, _rel, _flbl,0)909 : CONSTRUCT_FLAGS(_8|_ 16, _rel, _flbl,0);1026 us = I16 1027 ? CONSTRUCT_FLAGS(_8|_16, _rel, _flbl,0) 1028 : CONSTRUCT_FLAGS(_8|_32, _rel, _flbl,0); 910 1029 break; 911 1030 912 1031 case ASM_JUMPTYPE_NEAR: 913 1032 case_near: 914 us = I 32915 ? CONSTRUCT_FLAGS(_ 32, _rel, _flbl, 0)916 : CONSTRUCT_FLAGS(_ 16, _rel, _flbl, 0);1033 us = I16 1034 ? CONSTRUCT_FLAGS(_16, _rel, _flbl, 0) 1035 : CONSTRUCT_FLAGS(_32, _rel, _flbl, 0); 917 1036 break; 918 1037 case ASM_JUMPTYPE_SHORT: 919 1038 us = CONSTRUCT_FLAGS(_8, _rel, _flbl, 0); 920 1039 break; 921 1040 case ASM_JUMPTYPE_FAR: 922 us = I 32923 ? CONSTRUCT_FLAGS(_ 48, _rel, _flbl, 0)924 : CONSTRUCT_FLAGS(_ 32, _rel, _flbl, 0);1041 us = I16 1042 ? CONSTRUCT_FLAGS(_32, _rel, _flbl, 0) 1043 : CONSTRUCT_FLAGS(_48, _rel, _flbl, 0); 925 1044 break; 926 1045 default: 927 1046 assert(0); 928 1047 } 929 1048 return us; 930 1049 } 931 1050 if (!popnd->ptype) 932 1051 return CONSTRUCT_FLAGS(sz, _m, _normal, 0); 933 1052 ty = popnd->ptype->ty; 934 1053 if (ty == Tpointer && popnd->ptype->nextOf()->ty == Tfunction && 935 1054 !ps->isVarDeclaration()) 936 1055 { 937 1056 #if 1 938 1057 return CONSTRUCT_FLAGS(_32, _m, _fn16, 0); 939 1058 #else 940 1059 ty = popnd->ptype->Tnext->Tty; 941 1060 if (tyfarfunc(tybasic(ty))) { 942 1061 return I32 943 1062 ? CONSTRUCT_FLAGS(_48, _mnoi, _fn32, 0) 944 1063 : CONSTRUCT_FLAGS(_32, _mnoi, _fn32, 0); … … 957 1076 #else 958 1077 if (tyfarfunc(tybasic(ty))) 959 1078 return I32 960 1079 ? CONSTRUCT_FLAGS(_48, _p, _fn32, 0) 961 1080 : CONSTRUCT_FLAGS(_32, _p, _fn32, 0); 962 1081 else 963 1082 return I32 964 1083 ? CONSTRUCT_FLAGS(_32, _rel, _fn16, 0) 965 1084 : CONSTRUCT_FLAGS(_16, _rel, _fn16, 0); 966 1085 #endif 967 1086 } 968 1087 else if (asmstate.ucItype == ITjump) 969 1088 { amod = _normal; 970 1089 goto L1; 971 1090 } 972 1091 else 973 1092 return CONSTRUCT_FLAGS(sz, _m, _normal, 0); 974 1093 } 975 1094 if (popnd->segreg /*|| popnd->bPtr*/) 976 1095 { 977 amod = I 32 ? _addr32 : _addr16;1096 amod = I16 ? _addr16 : _addr32; 978 1097 if (asmstate.ucItype == ITjump) 979 1098 { 980 1099 L1: 981 1100 opty = _m; 982 if (I32) 1101 if (I16) 1102 { if (sz == _32) 1103 opty = _mnoi; 1104 } 1105 else 983 1106 { if (sz == _48) 984 opty = _mnoi;985 }986 else987 {988 if (sz == _32)989 1107 opty = _mnoi; 990 1108 } 991 1109 us = CONSTRUCT_FLAGS(sz,opty,amod,0); 992 1110 } 993 1111 else 994 1112 us = CONSTRUCT_FLAGS(sz, 995 1113 // _rel, amod, 0); 996 1114 _m, amod, 0); 997 1115 } 998 1116 999 1117 else if (popnd->ptype) 1000 1118 us = CONSTRUCT_FLAGS(sz, _imm, _normal, 0); 1001 1119 1002 1120 else if (popnd->disp >= CHAR_MIN && popnd->disp <= UCHAR_MAX) 1003 1121 us = CONSTRUCT_FLAGS(_8 | _16 | _32, _imm, _normal, 0); 1004 1122 else if (popnd->disp >= SHRT_MIN && popnd->disp <= USHRT_MAX) 1005 1123 us = CONSTRUCT_FLAGS(_16 | _32, _imm, _normal, 0); 1006 1124 else 1007 1125 us = CONSTRUCT_FLAGS(_32, _imm, _normal, 0); 1008 1126 return us; 1009 1127 } 1010 1128 1011 1129 /****************************** 1012 1130 * Convert assembly instruction into a code, and append 1013 1131 * it to the code generated for this block. 1014 1132 */ 1015 1133 1016 1134 STATIC code *asm_emit(Loc loc, 1017 1135 unsigned usNumops, PTRNTAB ptb, 1018 1136 OP *pop, 1019 1137 OPND *popnd1, OPND *popnd2, OPND *popnd3) 1020 1138 { 1021 1139 #ifdef DEBUG 1022 1140 unsigned char auchOpcode[16]; 1023 1141 unsigned usIdx = 0; 1024 1142 #define emit(op) (auchOpcode[usIdx++] = op) 1025 1143 #else 1026 1144 #define emit(op) ((void)(op)) 1027 1145 #endif 1028 1146 Identifier *id; 1029 // unsigned shortus;1147 // unsigned us; 1030 1148 unsigned char *puc; 1031 1149 unsigned usDefaultseg; 1032 1150 code *pc = NULL; 1033 1151 OPND *popndTmp; 1034 1152 ASM_OPERAND_TYPE aoptyTmp; 1035 unsigned shortuSizemaskTmp;1153 unsigned uSizemaskTmp; 1036 1154 REG *pregSegment; 1037 1155 code *pcPrefix = NULL; 1038 1156 unsigned uSizemask1 =0, uSizemask2 =0, uSizemask3 =0; 1039 1157 //ASM_OPERAND_TYPE aopty1 = _reg , aopty2 = 0, aopty3 = 0; 1040 1158 ASM_MODIFIERS amod1 = _normal, amod2 = _normal, amod3 = _normal; 1041 1159 unsigned uRegmask1 = 0, uRegmask2 =0, uRegmask3 =0; 1042 1160 unsigned uSizemaskTable1 =0, uSizemaskTable2 =0, 1043 1161 uSizemaskTable3 =0; 1044 1162 ASM_OPERAND_TYPE aoptyTable1 = _reg, aoptyTable2 = _reg, aoptyTable3 = _reg; 1045 1163 ASM_MODIFIERS amodTable1 = _normal, 1046 1164 amodTable2 = _normal, 1047 1165 amodTable3 = _normal; 1048 1166 unsigned uRegmaskTable1 = 0, uRegmaskTable2 =0, 1049 1167 uRegmaskTable3 =0; 1050 1168 1051 1169 pc = code_calloc(); 1052 1170 pc->Iflags |= CFpsw; // assume we want to keep the flags 1053 1171 if (popnd1) 1054 1172 { 1055 1173 uSizemask1 = ASM_GET_uSizemask(popnd1->usFlags); … … 1080 1198 uSizemaskTable2 = ASM_GET_uSizemask(ptb.pptb2->usOp2); 1081 1199 aoptyTable2 = ASM_GET_aopty(ptb.pptb2->usOp2); 1082 1200 amodTable2 = ASM_GET_amod(ptb.pptb2->usOp2); 1083 1201 uRegmaskTable2 = ASM_GET_uRegmask(ptb.pptb2->usOp2); 1084 1202 } 1085 1203 if (popnd3) 1086 1204 { 1087 1205 uSizemask3 = ASM_GET_uSizemask(popnd3->usFlags); 1088 1206 //aopty3 = ASM_GET_aopty(popnd3->usFlags); 1089 1207 amod3 = ASM_GET_amod(popnd3->usFlags); 1090 1208 uRegmask3 = ASM_GET_uRegmask(popnd3->usFlags); 1091 1209 1092 1210 uSizemaskTable3 = ASM_GET_uSizemask(ptb.pptb3->usOp3); 1093 1211 aoptyTable3 = ASM_GET_aopty(ptb.pptb3->usOp3); 1094 1212 amodTable3 = ASM_GET_amod(ptb.pptb3->usOp3); 1095 1213 uRegmaskTable3 = ASM_GET_uRegmask(ptb.pptb3->usOp3); 1096 1214 } 1097 1215 1098 1216 asmstate.statement->regs |= asm_modify_regs(ptb, popnd1, popnd2); 1099 1217 1100 if ( !I32&& ptb.pptb0->usFlags & _I386)1218 if (I16 && ptb.pptb0->usFlags & _I386) 1101 1219 { 1102 1220 switch (usNumops) 1103 1221 { 1104 1222 case 0: 1105 1223 break; 1106 1224 case 1: 1107 1225 if (popnd1 && popnd1->s) 1108 1226 { 1109 1227 L386_WARNING: 1110 1228 id = popnd1->s->ident; 1111 1229 L386_WARNING2: 1112 1230 if (config.target_cpu < TARGET_80386) 1113 1231 { // Reference to %s caused a 386 instruction to be generated 1114 1232 //warerr(WM_386_op, id->toChars()); 1115 1233 } 1116 1234 } 1117 1235 break; 1118 1236 case 2: 1119 1237 case 3: // The third operand is always an _imm 1120 1238 if (popnd1 && popnd1->s) 1121 1239 goto L386_WARNING; 1122 1240 if (popnd2 && popnd2->s) 1123 1241 { 1124 1242 id = popnd2->s->ident; 1125 1243 goto L386_WARNING2; 1126 1244 } 1127 1245 break; 1128 1246 } 1129 1247 } 1130 1248 1131 1249 switch (usNumops) 1132 1250 { 1133 1251 case 0: 1134 1252 if ((I32 && (ptb.pptb0->usFlags & _16_bit)) || 1135 ( !I32&& (ptb.pptb0->usFlags & _32_bit)))1253 (I16 && (ptb.pptb0->usFlags & _32_bit))) 1136 1254 { 1137 1255 emit(0x66); 1138 1256 pc->Iflags |= CFopsize; 1139 1257 } 1140 1258 break; 1141 1259 1142 1260 // 3 and 2 are the same because the third operand is always 1143 1261 // an immediate and does not affect operation size 1144 1262 case 3: 1145 1263 case 2: 1146 1264 if ((I32 && 1147 1265 (amod2 == _addr16 || 1148 1266 (uSizemaskTable2 & _16 && aoptyTable2 == _rel) || 1149 1267 (uSizemaskTable2 & _32 && aoptyTable2 == _mnoi) || 1150 1268 (ptb.pptb2->usFlags & _16_bit_addr) 1151 1269 ) 1152 1270 ) || 1153 ( !I32&&1271 (I16 && 1154 1272 (amod2 == _addr32 || 1155 1273 (uSizemaskTable2 & _32 && aoptyTable2 == _rel) || 1156 1274 (uSizemaskTable2 & _48 && aoptyTable2 == _mnoi) || 1157 1275 (ptb.pptb2->usFlags & _32_bit_addr))) 1158 1276 ) 1159 1277 { 1160 1278 emit(0x67); 1161 1279 pc->Iflags |= CFaddrsize; 1162 1280 if (I32) 1163 1281 amod2 = _addr16; 1164 1282 else 1165 1283 amod2 = _addr32; 1166 1284 popnd2->usFlags &= ~CONSTRUCT_FLAGS(0,0,7,0); 1167 1285 popnd2->usFlags |= CONSTRUCT_FLAGS(0,0,amod2,0); 1168 1286 } 1169 1287 1170 1288 1171 1289 /* Fall through, operand 1 controls the opsize, but the 1172 1290 address size can be in either operand 1 or operand 2, 1173 1291 hence the extra checking the flags tested for SHOULD 1174 1292 be mutex on operand 1 and operand 2 because there is 1175 1293 only one MOD R/M byte 1176 1294 */ 1177 1295 1178 1296 case 1: 1179 1297 if ((I32 && 1180 1298 (amod1 == _addr16 || 1181 1299 (uSizemaskTable1 & _16 && aoptyTable1 == _rel) || 1182 1300 (uSizemaskTable1 & _32 && aoptyTable1 == _mnoi) || 1183 1301 (ptb.pptb1->usFlags & _16_bit_addr))) || 1184 ( !I32&&1302 (I16 && 1185 1303 (amod1 == _addr32 || 1186 1304 (uSizemaskTable1 & _32 && aoptyTable1 == _rel) || 1187 1305 (uSizemaskTable1 & _48 && aoptyTable1 == _mnoi) || 1188 1306 (ptb.pptb1->usFlags & _32_bit_addr)))) 1189 1307 { 1190 1308 emit(0x67); // address size prefix 1191 1309 pc->Iflags |= CFaddrsize; 1192 1310 if (I32) 1193 1311 amod1 = _addr16; 1194 1312 else 1195 1313 amod1 = _addr32; 1196 1314 popnd1->usFlags &= ~CONSTRUCT_FLAGS(0,0,7,0); 1197 1315 popnd1->usFlags |= CONSTRUCT_FLAGS(0,0,amod1,0); 1198 1316 } 1199 1317 1200 1318 // If the size of the operand is unknown, assume that it is 1201 1319 // the default size 1202 1320 if ((I32 && (ptb.pptb0->usFlags & _16_bit)) || 1203 ( !I32&& (ptb.pptb0->usFlags & _32_bit)))1321 (I16 && (ptb.pptb0->usFlags & _32_bit))) 1204 1322 { 1205 1323 //if (asmstate.ucItype != ITjump) 1206 1324 { emit(0x66); 1207 1325 pc->Iflags |= CFopsize; 1208 1326 } 1209 1327 } 1210 1328 if (((pregSegment = (popndTmp = popnd1)->segreg) != NULL) || 1211 1329 ((popndTmp = popnd2) != NULL && 1212 1330 (pregSegment = popndTmp->segreg) != NULL) 1213 1331 ) 1214 1332 { 1215 1333 if ((popndTmp->pregDisp1 && 1216 1334 popndTmp->pregDisp1->val == _BP) || 1217 1335 popndTmp->pregDisp2 && 1218 1336 popndTmp->pregDisp2->val == _BP) 1219 1337 usDefaultseg = _SS; 1220 1338 else 1221 1339 usDefaultseg = _DS; 1222 1340 if (pregSegment->val != usDefaultseg) 1223 1341 switch (pregSegment->val) { … … 1733 1851 va_end(ap); 1734 1852 1735 1853 printf("\n"); 1736 1854 fflush(stdout); 1737 1855 1738 1856 longjmp(asmstate.env,1); 1739 1857 } 1740 1858 1741 1859 /******************************* 1742 1860 */ 1743 1861 1744 1862 STATIC opflag_t asm_float_type_size(Type *ptype, opflag_t *pusFloat) 1745 1863 { 1746 1864 *pusFloat = 0; 1747 1865 1748 1866 //printf("asm_float_type_size('%s')\n", ptype->toChars()); 1749 1867 if (ptype && ptype->isscalar()) 1750 1868 { 1751 1869 int sz = (int)ptype->size(); 1752 1870 if (sz == REALSIZE) 1753 { *pusFloat = _ 80;1871 { *pusFloat = _f80; 1754 1872 return 0; 1755 1873 } 1756 1874 switch (sz) 1757 1875 { 1758 1876 case 2: 1759 1877 return _16; 1760 1878 case 4: 1761 1879 return _32; 1762 1880 case 8: 1763 *pusFloat = _64; 1881 *pusFloat = _f64; 1882 return 0; 1883 case 10: 1884 *pusFloat = _f80; 1764 1885 return 0; 1765 1886 default: 1766 1887 break; 1767 1888 } 1768 1889 } 1769 1890 *pusFloat = _fanysize; 1770 1891 return _anysize; 1771 1892 } 1772 1893 1773 1894 /******************************* 1774 1895 */ 1775 1896 1776 1897 STATIC int asm_isint(OPND *o) 1777 1898 { 1778 1899 if (!o || o->base || o->s) 1779 1900 return 0; 1780 1901 //return o->disp != 0; 1781 1902 return 1; 1782 1903 } 1783 1904 … … 1993 2114 { 1994 2115 if (v->isParameter()) 1995 2116 asmstate.statement->refparam = TRUE; 1996 2117 1997 2118 v->checkNestedReference(asmstate.sc, asmstate.loc); 1998 2119 #if 0 1999 2120 if (!v->isDataseg() && v->parent != asmstate.sc->parent && v->parent) 2000 2121 { 2001 2122 asmerr(EM_uplevel, v->toChars()); 2002 2123 } 2003 2124 #endif 2004 2125 if (v->storage_class & STCfield) 2005 2126 { 2006 2127 o1->disp += v->offset; 2007 2128 goto L2; 2008 2129 } 2009 2130 if ((v->isConst() 2010 2131 #if DMDV2 2011 2132 || v->isImmutable() || v->storage_class & STCmanifest 2012 2133 #endif 2013 ) && !v->type->isfloating() )2134 ) && !v->type->isfloating() && v->init) 2014 2135 { ExpInitializer *ei = v->init->isExpInitializer(); 2015 2136 2016 2137 if (ei) 2017 2138 { 2018 2139 o1->disp = ei->exp->toInteger(); 2019 2140 return; 2020 2141 } 2021 2142 } 2022 2143 } 2023 2144 em = s->isEnumMember(); 2024 2145 if (em) 2025 2146 { 2026 2147 o1->disp = em->value->toInteger(); 2027 2148 return; 2028 2149 } 2029 2150 o1->s = s; // a C identifier 2030 2151 L2: 2031 2152 Declaration *d = s->isDeclaration(); 2032 2153 if (!d) 2033 2154 { 2034 2155 asmerr("%s %s is not a declaration", s->kind(), s->toChars()); 2035 2156 } 2036 2157 else if (d->getType()) 2037 2158 asmerr(EM_type_as_operand, d->getType()->toChars()); 2038 2159 else if (d->isTupleDeclaration()) 2039 2160 ; 2040 2161 else 2041 2162 o1->ptype = d->type->toBasetype(); 2042 2163 } 2043 2164 2044 2165 /**************************** 2045 2166 * Fill in the modregrm and sib bytes of code. 2046 2167 */ 2047 2168 2048 2169 STATIC void asm_make_modrm_byte( 2049 2170 #ifdef DEBUG 2050 2171 unsigned char *puchOpcode, unsigned *pusIdx, 2051 2172 #endif 2052 2173 code *pc, 2053 unsigned shortusFlags,2174 unsigned usFlags, 2054 2175 OPND *popnd, OPND *popnd2) 2055 2176 { 2056 2177 #undef modregrm 2057 2178 2058 2179 typedef union { 2059 2180 unsigned char uchOpcode; 2060 2181 struct { 2061 2182 unsigned rm : 3; 2062 2183 unsigned reg : 3; 2063 2184 unsigned mod : 2; 2064 2185 } modregrm; 2065 2186 } MODRM_BYTE; // mrmb 2066 2187 2067 2188 typedef union { 2068 2189 unsigned char uchOpcode; 2069 2190 struct { 2070 2191 unsigned base : 3; 2071 2192 unsigned index : 3; 2072 2193 unsigned ss : 2; 2073 2194 } sib; 2074 2195 } SIB_BYTE; 2075 2196 2076 2197 2077 2198 MODRM_BYTE mrmb = { 0 }; 2078 2199 SIB_BYTE sib = { 0 }; 2079 2200 char bSib = FALSE; 2080 2201 char bDisp = FALSE; 2081 2202 char b32bit = FALSE; 2082 2203 unsigned char *puc; 2083 2204 char bModset = FALSE; 2084 2205 Dsymbol *s; 2085 2206 2086 2207 unsigned uSizemask =0; 2087 2208 ASM_OPERAND_TYPE aopty; 2088 2209 ASM_MODIFIERS amod; 2089 unsigned shortuRegmask;2210 unsigned uRegmask; 2090 2211 unsigned char bOffsetsym = FALSE; 2091 2212 2092 2213 #if 0 2093 2214 printf("asm_make_modrm_byte(usFlags = x%x)\n", usFlags); 2094 2215 printf("op1: "); 2095 2216 asm_output_flags(popnd->usFlags); 2096 2217 if (popnd2) 2097 2218 { printf(" op2: "); 2098 2219 asm_output_flags(popnd2->usFlags); 2099 2220 } 2100 2221 printf("\n"); 2101 2222 #endif 2102 2223 2103 2224 uSizemask = ASM_GET_uSizemask(popnd->usFlags); 2104 2225 aopty = ASM_GET_aopty(popnd->usFlags); 2105 2226 amod = ASM_GET_amod(popnd->usFlags); 2106 2227 uRegmask = ASM_GET_uRegmask(popnd->usFlags); 2107 2228 s = popnd->s; 2108 2229 if (s) 2109 2230 { … … 2190 2311 } 2191 2312 mrmb.modregrm.reg = usFlags & NUM_MASK; 2192 2313 2193 2314 if (s && (aopty == _m || aopty == _mnoi) && !s->isLabel()) 2194 2315 { 2195 2316 if (s == asmstate.psLocalsize) 2196 2317 { 2197 2318 DATA_REF: 2198 2319 mrmb.modregrm.rm = BPRM; 2199 2320 if (amod == _addr16 || amod == _addr32) 2200 2321 mrmb.modregrm.mod = 0x2; 2201 2322 else 2202 2323 mrmb.modregrm.mod = 0x0; 2203 2324 } 2204 2325 else 2205 2326 { 2206 2327 Declaration *d = s->isDeclaration(); 2207 2328 assert(d); 2208 2329 if (d->isDataseg() || d->isCodeseg()) 2209 2330 { 2210 if (( I32 && amod == _addr16) ||2211 ( !I32&& amod == _addr32))2331 if ((I32 && amod == _addr16) || 2332 (I16 && amod == _addr32)) 2212 2333 asmerr(EM_bad_addr_mode); // illegal addressing mode 2213 2334 goto DATA_REF; 2214 2335 } 2215 2336 mrmb.modregrm.rm = BPRM; 2216 2337 mrmb.modregrm.mod = 0x2; 2217 2338 } 2218 2339 } 2219 2340 2220 2341 if (aopty == _reg || amod == _rspecial) { 2221 2342 mrmb.modregrm.mod = 0x3; 2222 2343 mrmb.modregrm.rm |= popnd->base->val; 2223 2344 } 2224 else if (amod == _addr16 || (amod == _flbl && !I32))2345 else if (amod == _addr16 || (amod == _flbl && I16)) 2225 2346 { unsigned rm; 2226 2347 2227 2348 #ifdef DEBUG 2228 2349 if (debuga) 2229 2350 printf("This is an ADDR16\n"); 2230 2351 #endif 2231 2352 if (!popnd->pregDisp1) 2232 2353 { rm = 0x6; 2233 2354 if (!s) 2234 2355 bDisp = TRUE; 2235 2356 } 2236 2357 else 2237 2358 { unsigned r1r2; 2238 2359 #define X(r1,r2) (((r1) * 16) + (r2)) 2239 2360 #define Y(r1) X(r1,9) 2240 2361 2241 2362 2242 2363 if (popnd->pregDisp2) 2243 2364 r1r2 = X(popnd->pregDisp1->val,popnd->pregDisp2->val); 2244 2365 else … … 2615 2736 } 2616 2737 2617 2738 /******************************* 2618 2739 * Match flags in operand against flags in opcode table. 2619 2740 * Returns: 2620 2741 * !=0 if match 2621 2742 */ 2622 2743 2623 2744 STATIC unsigned char asm_match_flags(opflag_t usOp, opflag_t usTable) 2624 2745 { 2625 2746 ASM_OPERAND_TYPE aoptyTable; 2626 2747 ASM_OPERAND_TYPE aoptyOp; 2627 2748 ASM_MODIFIERS amodTable; 2628 2749 ASM_MODIFIERS amodOp; 2629 2750 unsigned uRegmaskTable; 2630 2751 unsigned uRegmaskOp; 2631 2752 unsigned char bRegmatch; 2632 2753 unsigned char bRetval = FALSE; 2633 2754 unsigned uSizemaskOp; 2634 2755 unsigned uSizemaskTable; 2635 unsigned charbSizematch;2756 unsigned bSizematch; 2636 2757 2637 2758 //printf("asm_match_flags(usOp = x%x, usTable = x%x)\n", usOp, usTable); 2638 2759 if (asmstate.ucItype == ITfloat) 2639 2760 { 2640 2761 bRetval = asm_match_float_flags(usOp, usTable); 2641 2762 goto EXIT; 2642 2763 } 2643 2764 2644 2765 uSizemaskOp = ASM_GET_uSizemask(usOp); 2645 2766 uSizemaskTable = ASM_GET_uSizemask(usTable); 2646 2767 2647 2768 // Check #1, if the sizes do not match, NO match 2648 2769 bSizematch = (uSizemaskOp & uSizemaskTable); 2649 2770 2650 2771 amodOp = ASM_GET_amod(usOp); 2651 2772 2652 2773 aoptyTable = ASM_GET_aopty(usTable); 2653 2774 aoptyOp = ASM_GET_aopty(usOp); 2654 2775 2655 2776 // _mmm64 matches with a 64 bit mem or an MMX register … … 2741 2862 printf(": %s\n", bRetval ? "MATCH" : "NOMATCH"); 2742 2863 #endif 2743 2864 return bRetval; 2744 2865 2745 2866 Lmatch: 2746 2867 //printf("match\n"); 2747 2868 return 1; 2748 2869 } 2749 2870 2750 2871 /******************************* 2751 2872 */ 2752 2873 2753 2874 STATIC unsigned char asm_match_float_flags(opflag_t usOp, opflag_t usTable) 2754 2875 { 2755 2876 ASM_OPERAND_TYPE aoptyTable; 2756 2877 ASM_OPERAND_TYPE aoptyOp; 2757 2878 ASM_MODIFIERS amodTable; 2758 2879 ASM_MODIFIERS amodOp; 2759 2880 unsigned uRegmaskTable; 2760 2881 unsigned uRegmaskOp; 2761 unsigned charbRegmatch;2882 unsigned bRegmatch; 2762 2883 2763 2884 2764 2885 // 2765 2886 // Check #1, if the sizes do not match, NO match 2766 2887 // 2767 2888 uRegmaskOp = ASM_GET_uRegmask(usOp); 2768 2889 uRegmaskTable = ASM_GET_uRegmask(usTable); 2769 2890 bRegmatch = (uRegmaskTable & uRegmaskOp); 2770 2891 2771 2892 if (!(ASM_GET_uSizemask(usTable) & ASM_GET_uSizemask(usOp) || 2772 2893 bRegmatch)) 2773 2894 return(FALSE); 2774 2895 2775 2896 aoptyTable = ASM_GET_aopty(usTable); 2776 2897 aoptyOp = ASM_GET_aopty(usOp); 2777 2898 // 2778 2899 // The operand types must match, otherwise return FALSE. 2779 2900 // There is one exception for the _rm which is a table entry which matches 2780 2901 // _reg or _m 2781 2902 // … … 2824 2945 { 2825 2946 ASM_OPERAND_TYPE aopty = ASM_GET_aopty(usFlags); 2826 2947 ASM_MODIFIERS amod = ASM_GET_amod(usFlags); 2827 2948 unsigned uRegmask = ASM_GET_uRegmask(usFlags); 2828 2949 unsigned uSizemask = ASM_GET_uSizemask(usFlags); 2829 2950 2830 2951 if (uSizemask == _anysize) 2831 2952 printf("_anysize "); 2832 2953 else if (uSizemask == 0) 2833 2954 printf("0 "); 2834 2955 else 2835 2956 { 2836 2957 if (uSizemask & _8) 2837 2958 printf("_8 "); 2838 2959 if (uSizemask & _16) 2839 2960 printf("_16 "); 2840 2961 if (uSizemask & _32) 2841 2962 printf("_32 "); 2842 2963 if (uSizemask & _48) 2843 2964 printf("_48 "); 2965 if (uSizemask & _64) 2966 printf("_64 "); 2844 2967 } 2845 2968 2846 2969 printf("_"); 2847 2970 switch (aopty) { 2848 2971 case _reg: 2849 2972 printf("reg "); 2850 2973 break; 2851 2974 case _m: 2852 2975 printf("m "); 2853 2976 break; 2854 2977 case _imm: 2855 2978 printf("imm "); 2856 2979 break; 2857 2980 case _rel: 2858 2981 printf("rel "); 2859 2982 break; 2860 2983 case _mnoi: 2861 2984 printf("mnoi "); 2862 2985 break; 2863 2986 case _p: … … 2865 2988 break; 2866 2989 case _rm: 2867 2990 printf("rm "); 2868 2991 break; 2869 2992 case _float: 2870 2993 printf("float "); 2871 2994 break; 2872 2995 default: 2873 2996 printf(" UNKNOWN "); 2874 2997 } 2875 2998 2876 2999 printf("_"); 2877 3000 switch (amod) { 2878 3001 case _normal: 2879 3002 printf("normal "); 2880 3003 if (uRegmask & 1) printf("_al "); 2881 3004 if (uRegmask & 2) printf("_ax "); 2882 3005 if (uRegmask & 4) printf("_eax "); 2883 3006 if (uRegmask & 8) printf("_dx "); 2884 3007 if (uRegmask & 0x10) printf("_cl "); 3008 if (uRegmask & 0x40) printf("_rax "); 3009 if (uRegmask & 0x20) printf("_rplus_r "); 2885 3010 return; 2886 3011 case _rseg: 2887 3012 printf("rseg "); 2888 3013 break; 2889 3014 case _rspecial: 2890 3015 printf("rspecial "); 2891 3016 break; 2892 3017 case _addr16: 2893 3018 printf("addr16 "); 2894 3019 break; 2895 3020 case _addr32: 2896 3021 printf("addr32 "); 2897 3022 break; 2898 3023 case _fn16: 2899 3024 printf("fn16 "); 2900 3025 break; 2901 3026 case _fn32: 2902 3027 printf("fn32 "); 2903 3028 break; 2904 3029 case _flbl: … … 2960 3085 } 2961 3086 2962 3087 #endif 2963 3088 2964 3089 /******************************* 2965 3090 */ 2966 3091 2967 3092 STATIC REG *asm_reg_lookup(char *s) 2968 3093 { 2969 3094 int i; 2970 3095 2971 3096 //dbg_printf("asm_reg_lookup('%s')\n",s); 2972 3097 2973 3098 for (i = 0; i < sizeof(regtab) / sizeof(regtab[0]); i++) 2974 3099 { 2975 3100 if (strcmp(s,regtab[i].regstr) == 0) 2976 3101 { 2977 3102 return ®tab[i]; 2978 3103 } 2979 3104 } 3105 if (I64) 3106 { 3107 for (i = 0; i < sizeof(regtab64) / sizeof(regtab64[0]); i++) 3108 { 3109 if (strcmp(s,regtab64[i].regstr) == 0) 3110 { 3111 return ®tab64[i]; 3112 } 3113 } 3114 } 2980 3115 return NULL; 2981 3116 } 2982 3117 2983 3118 2984 3119 /******************************* 2985 3120 */ 2986 3121 2987 3122 STATIC void asm_token() 2988 3123 { 2989 3124 if (asmtok) 2990 3125 asmtok = asmtok->next; 2991 3126 asm_token_trans(asmtok); 2992 3127 } 2993 3128 2994 3129 /******************************* 2995 3130 */ 2996 3131 2997 3132 STATIC void asm_token_trans(Token *tok) 2998 3133 { 2999 3134 tok_value = TOKeof; … … 3016 3151 } 3017 3152 } 3018 3153 3019 3154 /******************************* 3020 3155 */ 3021 3156 3022 3157 STATIC unsigned asm_type_size(Type * ptype) 3023 3158 { unsigned u; 3024 3159 3025 3160 //if (ptype) printf("asm_type_size('%s') = %d\n", ptype->toChars(), (int)ptype->size()); 3026 3161 u = _anysize; 3027 3162 if (ptype && ptype->ty != Tfunction /*&& ptype->isscalar()*/) 3028 3163 { 3029 3164 switch ((int)ptype->size()) 3030 3165 { 3031 3166 case 0: asmerr(EM_bad_op, "0 size"); break; 3032 3167 case 1: u = _8; break; 3033 3168 case 2: u = _16; break; 3034 3169 case 4: u = _32; break; 3035 3170 case 6: u = _48; break; 3171 case 8: if (I64) u = _64; break; 3036 3172 } 3037 3173 } 3038 3174 return u; 3039 3175 } 3040 3176 3041 3177 /******************************* 3042 3178 * start of inline assemblers expression parser 3043 3179 * NOTE: functions in call order instead of alphabetical 3044 3180 */ 3045 3181 3046 3182 /******************************************* 3047 3183 * Parse DA expression 3048 3184 * 3049 3185 * Very limited define address to place a code 3050 3186 * address in the assembly 3051 3187 * Problems: 3052 3188 * o Should use dw offset and dd offset instead, 3053 3189 * for near/far support. 3054 3190 * o Should be able to add an offset to the label address. 3055 3191 * o Blocks addressed by DA should get their Bpred set correctly … … 4215 4351 * Return mask of registers used by block bp. 4216 4352 */ 4217 4353 4218 4354 regm_t iasm_regs(block *bp) 4219 4355 { 4220 4356 #ifdef DEBUG 4221 4357 if (debuga) 4222 4358 printf("Block iasm regs = 0x%X\n", bp->usIasmregs); 4223 4359 #endif 4224 4360 4225 4361 refparam |= bp->bIasmrefparam; 4226 4362 return bp->usIasmregs; 4227 4363 } 4228 4364 4229 4365 4230 4366 /************************ AsmStatement ***************************************/ 4231 4367 4232 4368 Statement *AsmStatement::semantic(Scope *sc) 4233 4369 { 4234 4370 //printf("AsmStatement::semantic()\n"); 4371 4372 #if DMDV2 4373 if (sc->func && sc->func->isSafe()) 4374 error("inline assembler not allowed in @safe function %s", sc->func->toChars()); 4375 #endif 4376 4235 4377 OP *o; 4236 4378 OPND *o1 = NULL,*o2 = NULL, *o3 = NULL; 4237 4379 PTRNTAB ptb; 4238 4380 unsigned usNumops; 4239 4381 unsigned char uchPrefix = 0; 4240 4382 unsigned char bAsmseen; 4241 4383 char *pszLabel = NULL; 4242 4384 code *c; 4243 4385 FuncDeclaration *fd = sc->parent->isFuncDeclaration(); 4244 4386 4245 4387 assert(fd); 4246 4388 fd->inlineAsm = 1; 4247 4389 4248 4390 if (!tokens) 4249 4391 return NULL; 4250 4392 4251 4393 memset(&asmstate, 0, sizeof(asmstate)); 4252 4394 4253 4395 asmstate.statement = this; 4254 4396 asmstate.sc = sc; trunk/src/backend/code.h
r569 r572 369 369 #define CFjmp16 2 // need 16 bit jump offset (long branch) 370 370 #define CFtarg 4 // this code is the target of a jump 371 371 #define CFseg 8 // get segment of immediate value 372 372 #define CFoff 0x10 // get offset of immediate value 373 373 #define CFss 0x20 // generate an SS: segment override (not with 374 374 // CFes at the same time, though!) 375 375 #define CFpsw 0x40 // we need the flags result after this instruction 376 376 #define CFopsize 0x80 // prefix with operand size 377 377 #define CFaddrsize 0x100 // prefix with address size 378 378 #define CFds 0x200 // need DS override (not with es, ss, or cs ) 379 379 #define CFcs 0x400 // need CS override 380 380 #define CFfs 0x800 // need FS override 381 381 #define CFgs (CFcs | CFfs) // need GS override 382 382 #define CFwait 0x1000 // If I32 it indicates when to output a WAIT 383 383 #define CFselfrel 0x2000 // if self-relative 384 384 #define CFunambig 0x4000 // indicates cannot be accessed by other addressing 385 385 // modes 386 386 #define CFtarg2 0x8000 // like CFtarg, but we can't optimize this away 387 387 #define CFvolatile 0x10000 // volatile reference, do not schedule 388 388 #define CFclassinit 0x20000 // class init code 389 #define CFoffset64 0x40000 // offset is 64 bits 389 390 390 391 #define CFPREFIX (CFSEG | CFopsize | CFaddrsize) 391 392 #define CFSEG (CFes | CFss | CFds | CFcs | CFfs | CFgs) 392 393 393 394 unsigned char Irex; // REX prefix 394 395 395 396 unsigned char Iop; 396 397 unsigned char Irm; // reg/mode 397 398 398 399 unsigned char Iop2; // second opcode byte 399 400 unsigned char Isib; // SIB byte 400 401 401 402 unsigned char Iop3; // third opcode byte 402 403 403 404 unsigned char IFL1,IFL2; // FLavors of 1st, 2nd operands 404 405 union evc IEV1; // 1st operand, if any 405 406 #define IEVpointer1 IEV1._EP.Vpointer 406 407 #define IEVseg1 IEV1._EP.Vseg 407 408 #define IEVsym1 IEV1.sp.Vsym 408 409 #define IEVdsym1 IEV1.dsp.Vsym trunk/src/backend/el.h
r442 r572 1 1 // Copyright (C) 1985-1995 by Symantec 2 // Copyright (C) 2000-20 09by Digital Mars2 // Copyright (C) 2000-2010 by Digital Mars 3 3 // All Rights Reserved 4 4 // http://www.digitalmars.com 5 5 // Written by Walter Bright 6 6 /* 7 7 * This source file is made available for personal use 8 8 * only. The license is in /dmd/src/dmd/backendlicense.txt 9 9 * or /dm/src/dmd/backendlicense.txt 10 10 * For any other uses, please contact Digital Mars. 11 11 */ 12 12 13 13 /* Routines to handle elems. */ 14 14 15 15 #if __SC__ 16 16 #pragma once 17 17 #endif 18 18 19 19 #ifndef EL_H 20 20 #define EL_H 1 21 21 22 22 #if TARGET_MAC … … 108 108 { 109 109 // Ety2: Must be in same position as Ety! 110 110 tym_t Ety2_; // data type (TYxxxx) 111 111 #define Ety2 _EU._EC.Ety2_ 112 112 unsigned char Ecomsub_; // number of remaining references to 113 113 // this common subexp (used to determine 114 114 // first, intermediate, and last references 115 115 // to a CSE) 116 116 #define Ecomsub _EU._EC.Ecomsub_ 117 117 118 118 #if TARGET_POWERPC 119 119 unsigned char Gflags; 120 120 #define GFLassrval 1 // element is rvalue of an assign 121 121 #define GFLsignok 2 // element does not need sign extend 122 122 #define GFLstrthis_fixed 4 // strthis child elem has been fixed 123 123 // on first pass, do not do it again 124 124 #endif 125 125 }_EC; 126 126 }_EU; 127 127 128 targ_size_t Enumbytes;// number of bytes for type if TYstruct | TYarray128 unsigned Enumbytes; // number of bytes for type if TYstruct | TYarray 129 129 TARGET_structELEM // target specific additions 130 130 Srcpos Esrcpos; // source file position 131 131 }; 132 132 133 133 #define typemask(e) ((!MARS && PARSER) ? (e)->ET->Tty : (e)->Ety ) 134 134 #define typetym(e) ((e)->ET->Tty) 135 135 #define el_fl(e) ((enum FL)((e)->EV.sp.Vsym->Sfl)) 136 136 #define Eoffset EV.sp.Voffset 137 137 #define Esymnum EV.sp.Vsymnum 138 138 139 139 #define list_elem(list) ((elem *) list_ptr(list)) 140 140 #define list_setelem(list,ptr) list_ptr(list) = (elem *)(ptr) 141 141 #define cnst(e) ((e)->Eoper == OPconst) /* Determine if elem is a constant */ 142 142 #define E1 EV.eop.Eleft /* left child */ 143 143 #define E2 EV.eop.Eright /* right child */ 144 144 #define Erd EV.sp.spu.Erd // reaching definition 145 145 146 146 #define el_int(a,b) el_long(a,b) 147 147 148 148 typedef elem *elem_p; /* try to reduce the symbol table size */ trunk/src/backend/elfobj.c
r569 r572 41 41 //#define DEBSYM 0x7E 42 42 43 43 static Outbuffer *fobjbuf; 44 44 45 45 regm_t BYTEREGS = BYTEREGS_INIT; 46 46 regm_t ALLREGS = ALLREGS_INIT; 47 47 48 48 static char __file__[] = __FILE__; // for tassert.h 49 49 #include "tassert.h" 50 50 51 51 #define MATCH_SECTION 1 52 52 53 53 #define DEST_LEN (IDMAX + IDOHD + 1) 54 54 char *obj_mangle2(Symbol *s,char *dest); 55 55 56 56 #if MARS 57 57 // C++ name mangling is handled by front end 58 58 #define cpp_mangle(s) ((s)->Sident) 59 59 #endif 60 60 61 /*************************************************** 62 * Correspondence of relocation types 63 * 386 32 bit in 64 64 in 64 64 * RI_TYPE_SYM32 R_X86_64_32 R_X86_64_64 65 * RI_TYPE_GOTOFF R_X86_64_PC32 R_X86_64_ 66 * RI_TYPE_GOTPC R_X86_64_ R_X86_64_ 67 * RI_TYPE_GOT32 R_X86_64_ R_X86_64_ 68 * RI_TYPE_TLS_GD R_X86_64_TLSGD R_X86_64_ 69 * RI_TYPE_TLS_IE R_X86_64_GOTTPOFF R_X86_64_ 70 * RI_TYPE_TLS_LE R_X86_64_TPOFF32 R_X86_64_ 71 * RI_TYPE_PLT32 R_X86_64_PLT32 R_X86_64_ 72 * RI_TYPE_PC32 R_X86_64_PC32 R_X86_64_ 73 */ 61 74 62 75 /****************************************** 63 76 */ 64 77 65 78 symbol *GOTsym; // global offset table reference 66 79 67 80 symbol *elfobj_getGOTsym() 68 81 { 69 82 if (!GOTsym) 70 83 { 71 84 GOTsym = symbol_name("_GLOBAL_OFFSET_TABLE_",SCglobal,tspvoid); 72 85 } 73 86 return GOTsym; 74 87 } 75 88 76 89 static void objfile_write(FILE *fd, void *buffer, unsigned len); 77 90 78 91 STATIC char * objmodtoseg (const char *modname); 79 92 STATIC void obj_browse_flush(); 80 93 STATIC void objfixupp (struct FIXUP *); 81 94 STATIC void ledata_new (int seg,targ_size_t offset); 82 static int obj_align(Symbol *s);83 95 void obj_tlssections(); 84 96 85 97 static IDXSYM elf_addsym(IDXSTR sym, targ_size_t val, unsigned sz, 86 98 unsigned typ,unsigned bind,IDXSEC sec); 87 99 static long elf_align(FILE *fd, targ_size_t size, long offset); 88 100 89 101 // The object file is built is several separate pieces 90 102 91 103 // Non-repeatable section types have single output buffers 92 104 // Pre-allocated buffers are defined for: 93 105 // Section Names string table 94 106 // Section Headers table 95 107 // Symbol table 96 108 // String table 97 109 // Notes section 98 110 // Comment data 99 111 100 112 // Section Names - String table for section names only 101 113 static Outbuffer *section_names; 102 114 #define SEC_NAMES_INIT 800 … … 1236 1248 { 1237 1249 //dbg_printf("obj_exestr(char *%s)\n",p); 1238 1250 } 1239 1251 1240 1252 /************************** 1241 1253 * Embed string in obj. 1242 1254 */ 1243 1255 1244 1256 void obj_user(const char *p) 1245 1257 { 1246 1258 //dbg_printf("obj_user(char *%s)\n",p); 1247 1259 } 1248 1260 1249 1261 /******************************* 1250 1262 * Output a weak extern record. 1251 1263 */ 1252 1264 1253 1265 void obj_wkext(Symbol *s1,Symbol *s2) 1254 1266 { 1255 1267 //dbg_printf("obj_wkext(Symbol *%s,Symbol *s2)\n",s1->Sident,s2->Sident); 1256 #if 01257 char buffer[2+2+2];1258 int i;1259 1260 buffer[0] = 0x80;1261 buffer[1] = 0xA8;1262 i = 2;1263 i += insidx(&buffer[2],s1->Sxtrnnum);1264 i += insidx(&buffer[i],s2->Sxtrnnum);1265 objrecord(COMENT,buffer,i);1266 #endif1267 1268 } 1268 1269 1269 1270 /******************************* 1270 1271 * Output file name record. 1271 1272 * 1272 1273 * Currently assumes that obj_filename will not be called 1273 1274 * twice for the same file. 1274 1275 */ 1275 1276 1276 1277 void obj_filename(const char *modname) 1277 { unsigned strtab_idx; 1278 unsigned symtab_idx; 1279 1278 { 1280 1279 //dbg_printf("obj_filename(char *%s)\n",modname); 1281 strtab_idx = elf_addstr(symtab_strings,modname);1280 unsigned strtab_idx = elf_addstr(symtab_strings,modname); 1282 1281 elf_addsym(strtab_idx,0,0,STT_FILE,STB_LOCAL,SHT_ABS); 1283 1282 } 1284 1283 1285 1284 /******************************* 1286 1285 * Embed compiler version in .obj file. 1287 1286 */ 1288 1287 1289 1288 void obj_compiler() 1290 1289 { 1291 1290 //dbg_printf("obj_compiler\n"); 1292 1291 comment_data = new Outbuffer(); 1293 1292 comment_data->write(compiler,sizeof(compiler)); 1294 1293 //dbg_printf("Comment data size %d\n",comment_data->size()); 1295 1294 } 1296 1295 1297 #if 01298 /********************************1299 * Convert module name to code segment name.1300 * Output:1301 * mem_malloc'd code seg name1302 */1303 1304 STATIC char * objmodtoseg(const char *modname)1305 { char *csegname = NULL;1306 1307 if (LARGECODE) // if need to add in module name1308 { int i;1309 char *m;1310 static const char suffix[] = "_TEXT";1311 1312 // Prepend the module name to the beginning of the _TEXT1313 m = filespecgetroot(filespecname(modname));1314 strupr(m);1315 i = strlen(m);1316 csegname = mem_malloc(i + sizeof(suffix));1317 strcpy(csegname,m);1318 strcat(csegname,suffix);1319 mem_free(m);1320 }1321 return csegname;1322 }1323 #endif1324 1296 1325 1297 //#if NEWSTATICDTOR 1326 1298 1327 1299 /************************************** 1328 1300 * Symbol is the function that calls the static constructors. 1329 1301 * Put a pointer to it into a special segment that the startup code 1330 1302 * looks at. 1331 1303 * Input: 1332 1304 * s static constructor function 1333 1305 * dtor !=0 if leave space for static destructor 1334 1306 * seg 1: user 1335 1307 * 2: lib 1336 1308 * 3: compiler 1337 1309 */ 1338 1310 1339 1311 void obj_staticctor(Symbol *s,int dtor,int none) 1340 1312 { 1341 1313 // Static constructors and destructors 1342 1314 IDXSEC seg; 1343 1315 Outbuffer *buf; 1344 1316 1345 1317 //dbg_printf("obj_staticctor(%s) offset %x\n",s->Sident,s->Soffset); 1346 1318 //symbol_print(s); 1347 1319 s->Sseg = seg = 1348 1320 elf_getsegment(".ctors", NULL, SHT_PROGDEF, SHF_ALLOC|SHF_WRITE, 4); 1349 1321 buf = SegData[seg]->SDbuf; 1350 1322 if (I64) 1351 1323 buf->write64(s->Soffset); 1352 1324 else 1353 1325 buf->write32(s->Soffset); 1354 elf_addrel(seg,SegData[seg]->SDoffset, RI_TYPE_SYM32,STI_TEXT,0);1326 elf_addrel(seg,SegData[seg]->SDoffset,I64 ? R_X86_64_64 : RI_TYPE_SYM32,STI_TEXT,0); 1355 1327 SegData[seg]->SDoffset = buf->size(); 1356 1328 } 1357 1329 1358 1330 /************************************** 1359 1331 * Symbol is the function that calls the static destructors. 1360 1332 * Put a pointer to it into a special segment that the exit code 1361 1333 * looks at. 1362 1334 * Input: 1363 1335 * s static destructor function 1364 1336 */ 1365 1337 1366 1338 void obj_staticdtor(Symbol *s) 1367 1339 { 1368 1340 IDXSEC seg; 1369 1341 Outbuffer *buf; 1370 1342 1371 1343 //dbg_printf("obj_staticdtor(%s) offset %x\n",s->Sident,s->Soffset); 1372 1344 //symbol_print(s); 1373 1345 seg = elf_getsegment(".dtors", NULL, SHT_PROGDEF, SHF_ALLOC|SHF_WRITE, 4); 1374 1346 buf = SegData[seg]->SDbuf; 1375 1347 if (I64) 1376 1348 buf->write64(s->Soffset); 1377 1349 else 1378 1350 buf->write32(s->Soffset); 1379 //elf_addrel(seg,0,RI_TYPE_SYM32,STI_TEXT,0); 1380 elf_addrel(seg,SegData[seg]->SDoffset,RI_TYPE_SYM32,s->Sxtrnnum,0); 1351 elf_addrel(seg,SegData[seg]->SDoffset,I64 ? R_X86_64_64 : RI_TYPE_SYM32,s->Sxtrnnum,0); 1381 1352 SegData[seg]->SDoffset = buf->size(); 1382 1353 } 1383 1354 1384 1355 //#else 1385 1356 1386 1357 /*************************************** 1387 1358 * Stuff pointer to function in its own segment. 1388 1359 * Used for static ctor and dtor lists. 1389 1360 */ 1390 1361 1391 1362 void obj_funcptr(Symbol *s) 1392 1363 { 1393 1364 //dbg_printf("obj_funcptr(%s) \n",s->Sident); 1394 1365 } 1395 1366 1396 1367 //#endif 1397 1368 1398 1369 /*************************************** 1399 1370 * Stuff the following data in a separate segment: 1400 1371 * pointer to function 1401 1372 * pointer to ehsym 1402 1373 * length of function 1403 1374 */ 1404 1375 1405 1376 void obj_ehtables(Symbol *sfunc,targ_size_t size,Symbol *ehsym) 1406 1377 { 1407 1378 //dbg_printf("obj_ehtables(%s) \n",sfunc->Sident); 1408 1379 1409 symbol *ehtab_entry; 1410 dt_t **pdte; 1411 1412 ehtab_entry = symbol_generate(SCstatic,type_alloc(TYint)); 1380 symbol *ehtab_entry = symbol_generate(SCstatic,type_alloc(TYint)); 1413 1381 symbol_keep(ehtab_entry); 1414 1382 elf_getsegment(".deh_beg", NULL, SHT_PROGDEF, SHF_ALLOC, 4); 1415 1383 ehtab_entry->Sseg = elf_getsegment(".deh_eh", NULL, SHT_PROGDEF, SHF_ALLOC, 4); 1416 1384 elf_getsegment(".deh_end", NULL, SHT_PROGDEF, SHF_ALLOC, 4); 1417 1385 ehtab_entry->Stype->Tmangle = mTYman_c; 1418 1386 ehsym->Stype->Tmangle = mTYman_c; 1419 pdte = &ehtab_entry->Sdt;1387 dt_t **pdte = &ehtab_entry->Sdt; 1420 1388 pdte = dtxoff(pdte,sfunc,0,TYnptr); 1421 1389 pdte = dtxoff(pdte,ehsym,0,TYnptr); 1422 1390 pdte = dtnbytes(pdte,4,(char *)&sfunc->Ssize); 1423 1391 outdata(ehtab_entry); 1424 1392 } 1425 1393 1426 1394 /********************************************* 1427 1395 * Put out symbols that define the beginning/end of the .deh_eh section. 1428 1396 */ 1429 1397 1430 1398 void obj_ehsections() 1431 { int sec; 1432 IDXSYM symidx; 1433 IDXSTR namidx; 1434 1435 sec = elf_getsegment(".deh_beg", NULL, SHT_PROGDEF, SHF_ALLOC, 4); 1399 { 1400 int sec = elf_getsegment(".deh_beg", NULL, SHT_PROGDEF, SHF_ALLOC, 4); 1436 1401 //obj_bytes(sec, 0, 4, NULL); 1437 1402 1438 namidx = elf_addstr(symtab_strings,"_deh_beg");1403 IDXSTR namidx = elf_addstr(symtab_strings,"_deh_beg"); 1439 1404 elf_addsym(namidx, 0, 0, STT_OBJECT, STB_GLOBAL, MAP_SEG2SECIDX(sec)); 1440 1405 //elf_addsym(namidx, 0, 4, STT_OBJECT, STB_GLOBAL, MAP_SEG2SECIDX(sec)); 1441 1406 1442 1407 elf_getsegment(".deh_eh", NULL, SHT_PROGDEF, SHF_ALLOC, 4); 1443 1408 1444 1409 sec = elf_getsegment(".deh_end", NULL, SHT_PROGDEF, SHF_ALLOC, 4); 1445 1410 namidx = elf_addstr(symtab_strings,"_deh_end"); 1446 1411 elf_addsym(namidx, 0, 0, STT_OBJECT, STB_GLOBAL, MAP_SEG2SECIDX(sec)); 1447 1412 1448 1413 obj_tlssections(); 1449 1414 } 1450 1415 1451 1416 /********************************************* 1452 1417 * Put out symbols that define the beginning/end of the thread local storage sections. 1453 1418 */ 1454 1419 1455 1420 void obj_tlssections() 1456 1421 { 1457 1422 IDXSTR namidx; 1458 1423 … … 1676 1641 * won't be storing D gc roots in their tls. 1677 1642 * Output: 1678 1643 * seg_tlsseg set to segment number for TLS segment. 1679 1644 * Returns: 1680 1645 * segment for TLS segment 1681 1646 */ 1682 1647 1683 1648 seg_data *obj_tlsseg() 1684 1649 { 1685 1650 /* Ensure that ".tdata" precedes any other .tdata. section, as the ld 1686 1651 * linker script fails to work right. 1687 1652 */ 1688 1653 elf_getsegment(".tdata", NULL, SHT_PROGDEF, SHF_ALLOC|SHF_WRITE|SHF_TLS, 4); 1689 1654 1690 1655 static const char tlssegname[] = ".tdata."; 1691 1656 //dbg_printf("obj_tlsseg(\n"); 1692 1657 1693 1658 if (seg_tlsseg == UNKNOWN) 1694 1659 { 1695 1660 seg_tlsseg = elf_getsegment(tlssegname, NULL, SHT_PROGDEF, 1696 SHF_ALLOC|SHF_WRITE|SHF_TLS, 4);1661 SHF_ALLOC|SHF_WRITE|SHF_TLS, I64 ? 16 : 4); 1697 1662 } 1698 1663 return SegData[seg_tlsseg]; 1699 1664 } 1700 1665 1701 1666 1702 1667 /********************************* 1703 1668 * Define segments for Thread Local Storage. 1704 1669 * Output: 1705 1670 * seg_tlsseg_bss set to segment number for TLS segment. 1706 1671 * Returns: 1707 1672 * segment for TLS segment 1708 1673 */ 1709 1674 1710 1675 seg_data *obj_tlsseg_bss() 1711 1676 { 1712 1677 static const char tlssegname[] = ".tbss"; 1713 1678 //dbg_printf("obj_tlsseg_bss(\n"); 1714 1679 1715 1680 if (seg_tlsseg_bss == UNKNOWN) 1716 1681 { 1717 1682 seg_tlsseg_bss = elf_getsegment(tlssegname, NULL, SHT_NOBITS, 1718 SHF_ALLOC|SHF_WRITE|SHF_TLS, 4);1683 SHF_ALLOC|SHF_WRITE|SHF_TLS, I64 ? 16 : 4); 1719 1684 } 1720 1685 return SegData[seg_tlsseg_bss]; 1721 1686 } 1722 1687 1723 1688 1724 1689 /******************************* 1725 1690 * Output an alias definition record. 1726 1691 */ 1727 1692 1728 1693 void obj_alias(const char *n1,const char *n2) 1729 { unsigned len; 1730 char *buffer; 1731 1694 { 1732 1695 dbg_printf("obj_alias(%s,%s)\n",n1,n2); 1733 1696 assert(0); 1734 1697 #if NOT_DONE 1735 buffer = (char *) alloca(strlen(n1) + strlen(n2) + 2 * ONS_OHD);1736 len = obj_namestring(buffer,n1);1698 char *buffer = (char *) alloca(strlen(n1) + strlen(n2) + 2 * ONS_OHD); 1699 unsigned len = obj_namestring(buffer,n1); 1737 1700 len += obj_namestring(buffer + len,n2); 1738 1701 objrecord(ALIAS,buffer,len); 1739 1702 #endif 1740 1703 } 1741 1704 1742 char *unsstr (unsigned value)1743 { 1744 static char buffer [64];1745 1746 sprintf (buffer, "%d", value);1705 char *unsstr(unsigned value) 1706 { 1707 static char buffer[64]; 1708 1709 sprintf(buffer, "%d", value); 1747 1710 return buffer; 1748 1711 } 1749 1712 1750 1713 /******************************* 1751 1714 * Mangle a name. 1752 1715 * Returns: 1753 1716 * mangled name 1754 1717 */ 1755 1718 1756 1719 char *obj_mangle2(Symbol *s,char *dest) 1757 1720 { 1758 size_t len;1759 1721 char *name; 1760 1722 1761 1723 //dbg_printf("obj_mangle('%s'), mangle = x%x\n",s->Sident,type_mangle(s->Stype)); 1762 1724 symbol_debug(s); 1763 1725 assert(dest); 1764 1726 #if SCPP 1765 1727 name = CPP ? cpp_mangle(s) : s->Sident; 1766 1728 #elif MARS 1767 1729 name = cpp_mangle(s); 1768 1730 #else 1769 1731 name = s->Sident; 1770 1732 #endif 1771 len = strlen(name); // # of bytes in name1733 size_t len = strlen(name); // # of bytes in name 1772 1734 //dbg_printf("len %d\n",len); 1773 1735 switch (type_mangle(s->Stype)) 1774 1736 { 1775 1737 case mTYman_pas: // if upper case 1776 1738 case mTYman_for: 1777 1739 if (len >= DEST_LEN) 1778 1740 dest = (char *)mem_malloc(len + 1); 1779 1741 memcpy(dest,name,len + 1); // copy in name and ending 0 1780 1742 for (int i = 0; 1; i++) 1781 1743 { char c = dest[i]; 1782 1744 if (!c) 1783 1745 break; 1784 1746 if (c >= 'a' && c <= 'z') 1785 1747 dest[i] = c + 'A' - 'a'; 1786 1748 } 1787 1749 break; 1788 1750 case mTYman_std: 1789 1751 #if TARGET_LINUX || TARGET_FREEBSD || TARGET_SOLARIS 1790 1752 if (tyfunc(s->ty()) && !variadic(s->Stype)) 1791 1753 #else … … 1815 1777 memcpy(dest,name,len+1);// copy in name and trailing 0 1816 1778 break; 1817 1779 1818 1780 default: 1819 1781 #ifdef DEBUG 1820 1782 printf("mangling %x\n",type_mangle(s->Stype)); 1821 1783 symbol_print(s); 1822 1784 #endif 1823 1785 printf("%d\n", type_mangle(s->Stype)); 1824 1786 assert(0); 1825 1787 } 1826 1788 //dbg_printf("\t %s\n",dest); 1827 1789 return dest; 1828 1790 } 1829 1791 1830 1792 /******************************* 1831 1793 * Export a function name. 1832 1794 */ 1833 1795 1834 1796 void obj_export(Symbol *s,unsigned argsize) 1835 { char *coment; 1836 size_t len; 1837 1797 { 1838 1798 //dbg_printf("obj_export(%s,%d)\n",s->Sident,argsize); 1839 1799 1840 1800 } 1841 1801 1842 1802 /******************************* 1843 1803 * Update data information about symbol 1844 1804 * align for output and assign segment 1845 1805 * if not already specified. 1846 1806 * 1847 1807 * Input: 1848 1808 * sdata data symbol 1849 1809 * datasize output size 1850 1810 * seg default seg if not known 1851 1811 * Returns: 1852 1812 * actual seg 1853 1813 */ 1854 1814 1855 1815 int elf_data_start(Symbol *sdata, targ_size_t datasize, int seg) 1856 1816 { 1857 1817 targ_size_t alignbytes; … … 1985 1944 return symidx; 1986 1945 } 1987 1946 1988 1947 int objextdef(const char *name) 1989 1948 { 1990 1949 return objextern(name); 1991 1950 } 1992 1951 1993 1952 /******************************* 1994 1953 * Output an external for existing symbol. 1995 1954 * Input: 1996 1955 * s Symbol to do EXTDEF on 1997 1956 * (Name is to be mangled) 1998 1957 * Returns: 1999 1958 * Symbol table index of the definition 2000 1959 * NOTE: Numbers will not be linear. 2001 1960 */ 2002 1961 2003 1962 int objextern(Symbol *s) 2004 1963 { 2005 IDXSTR namidx;2006 1964 int symtype,sectype; 2007 targ_size_tsize;1965 unsigned size; 2008 1966 2009 1967 //dbg_printf("objextern('%s') %x\n",s->Sident,s->Svalue); 2010 1968 symbol_debug(s); 2011 namidx = elf_addmangled(s);1969 IDXSTR namidx = elf_addmangled(s); 2012 1970 2013 1971 #if SCPP 2014 1972 if (s->Sscope && !tyfunc(s->ty())) 2015 1973 { 2016 1974 symtype = STT_OBJECT; 2017 1975 sectype = SHT_COMMON; 2018 1976 size = type_size(s->Stype); 2019 1977 } 2020 1978 else 2021 1979 #endif 2022 1980 { 2023 1981 symtype = STT_NOTYPE; 2024 1982 sectype = SHT_UNDEF; 2025 1983 size = 0; 2026 1984 } 2027 1985 if (s->ty() & mTYthread) 2028 1986 { 2029 1987 //printf("objextern('%s') %x TLS\n",s->Sident,s->Svalue); 2030 1988 symtype = STT_TLS; 2031 1989 } … … 2034 1992 /*(s->ty() & mTYweak) ? STB_WEAK : */STB_GLOBAL, sectype); 2035 1993 return s->Sxtrnnum; 2036 1994 2037 1995 } 2038 1996 2039 1997 /******************************* 2040 1998 * Output a common block definition. 2041 1999 * Input: 2042 2000 * p -> external identifier 2043 2001 * size size in bytes of each elem 2044 2002 * count number of elems 2045 2003 * Returns: 2046 2004 * Symbol table index for symbol 2047 2005 */ 2048 2006 2049 2007 int obj_comdef(Symbol *s,targ_size_t size,targ_size_t count) 2050 2008 { 2051 2009 //printf("obj_comdef('%s',%d,%d)\n",s->Sident,size,count); 2052 2010 symbol_debug(s); 2053 2011 2012 int align = I64 ? 16 : 4; 2054 2013 if (s->ty() & mTYthread) 2055 2014 { 2056 2015 s->Sseg = elf_getsegment(".tbss.", cpp_mangle(s), 2057 SHT_NOBITS, SHF_ALLOC|SHF_WRITE|SHF_TLS, 4);2016 SHT_NOBITS, SHF_ALLOC|SHF_WRITE|SHF_TLS, align); 2058 2017 s->Sfl = FLtlsdata; 2059 2018 SegData[s->Sseg]->SDsym = s; 2060 2019 SegData[s->Sseg]->SDoffset += size * count; 2061 2020 objpubdef(s->Sseg, s, 0); 2062 2021 searchfixlist(s); 2063 2022 return s->Sseg; 2064 2023 } 2065 2024 else 2066 2025 { 2067 2026 s->Sseg = elf_getsegment(".bss.", cpp_mangle(s), 2068 SHT_NOBITS, SHF_ALLOC|SHF_WRITE, 4);2027 SHT_NOBITS, SHF_ALLOC|SHF_WRITE, align); 2069 2028 s->Sfl = FLudata; 2070 2029 SegData[s->Sseg]->SDsym = s; 2071 2030 SegData[s->Sseg]->SDoffset += size * count; 2072 2031 objpubdef(s->Sseg, s, 0); 2073 2032 searchfixlist(s); 2074 2033 return s->Sseg; 2075 2034 } 2076 2035 #if 0 2077 2036 IDXSTR namidx = elf_addmangled(s); 2078 2037 alignOffset(UDATA,size); 2079 2038 IDXSYM symidx = elf_addsym(namidx, SegData[UDATA]->SDoffset, size*count, 2080 2039 (s->ty() & mTYthread) ? STT_TLS : STT_OBJECT, 2081 2040 STB_WEAK, SHI_BSS); 2082 2041 //dbg_printf("\tobj_comdef returning symidx %d\n",symidx); 2083 2042 s->Sseg = UDATA; 2084 2043 s->Sfl = FLudata; 2085 2044 SegData[UDATA]->SDoffset += size * count; 2086 2045 return symidx; 2087 2046 #endif 2088 2047 } … … 2345 2304 * reftodatseg(DATA,offset,3 * sizeof(int *),UDATA); 2346 2305 */ 2347 2306 2348 2307 void reftodatseg(int seg,targ_size_t offset,targ_size_t val, 2349 2308 unsigned targetdatum,int flags) 2350 2309 { 2351 2310 Outbuffer *buf; 2352 2311 int save; 2353 2312 2354 2313 buf = SegData[seg]->SDbuf; 2355 2314 save = buf->size(); 2356 2315 buf->setsize(offset); 2357 2316 //dbg_printf("reftodatseg(seg=%d, offset=x%lx, val=x%lx,data %x, flags %x )\n", 2358 2317 // seg,offset,val,targetdatum,flags); 2359 2318 /*if (OPT_IS_SET(OPTfwritable_strings)) 2360 2319 { 2361 2320 elf_addrel(seg,offset,RI_TYPE_SYM32,STI_DATA,0); 2362 2321 } 2363 2322 else*/ 2364 2323 { 2365 unsigned type = RI_TYPE_SYM32; 2366 2367 if (MAP_SEG2TYP(seg) == CODE && config.flags3 & CFG3pic) 2368 type = RI_TYPE_GOTOFF; 2369 else if (MAP_SEG2SEC(targetdatum)->sh_flags & SHF_TLS) 2370 type = config.flags3 & CFG3pic ? RI_TYPE_TLS_GD : RI_TYPE_TLS_LE; 2371 2372 elf_addrel(seg,offset,type,STI_RODAT,0); 2373 } 2374 if (I64) 2375 buf->write64(val); 2376 else 2377 buf->write32(val); 2378 if (save > offset + NPTRSIZE) 2324 int relinfo; 2325 2326 if (I64) 2327 { 2328 if (MAP_SEG2TYP(seg) == CODE && config.flags3 & CFG3pic) 2329 relinfo = R_X86_64_PC32; 2330 else if (MAP_SEG2SEC(targetdatum)->sh_flags & SHF_TLS) 2331 relinfo = config.flags3 & CFG3pic ? R_X86_64_TLSGD : R_X86_64_TPOFF32; 2332 else 2333 relinfo = R_X86_64_32; 2334 } 2335 else 2336 { 2337 if (MAP_SEG2TYP(seg) == CODE && config.flags3 & CFG3pic) 2338 relinfo = RI_TYPE_GOTOFF; 2339 else if (MAP_SEG2SEC(targetdatum)->sh_flags & SHF_TLS) 2340 relinfo = config.flags3 & CFG3pic ? RI_TYPE_TLS_GD : RI_TYPE_TLS_LE; 2341 else 2342 relinfo = RI_TYPE_SYM32; 2343 } 2344 2345 elf_addrel(seg, offset, relinfo, STI_RODAT, 0); 2346 } 2347 buf->write32(val); 2348 if (save > offset + 4) 2379 2349 buf->setsize(save); 2380 2350 } 2381 2351 2382 2352 /******************************* 2383 2353 * Refer to address that is in the code segment. 2384 2354 * Only offsets are output, regardless of the memory model. 2385 2355 * Used to put values in switch address tables. 2386 2356 * Input: 2387 2357 * seg = where the address is going (CODE or DATA) 2388 2358 * offset = offset within seg 2389 2359 * val = displacement from start of this module 2390 2360 */ 2391 2361 2392 2362 void reftocodseg(int seg,targ_size_t offset,targ_size_t val) 2393 2363 { 2394 2364 Outbuffer *buf; 2395 2365 int save; 2396 2366 int segtyp = MAP_SEG2TYP(seg); 2397 2367 2398 2368 //dbg_printf("reftocodseg(seg=%d, offset=x%lx, val=x%lx )\n",seg,offset,val); 2399 2369 assert(seg > 0); // COMDATs not done yet 2400 2370  
