i386-gen.c 32 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165
  1. /*
  2. * X86 code generator for TCC
  3. *
  4. * Copyright (c) 2001-2004 Fabrice Bellard
  5. *
  6. * This library is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU Lesser General Public
  8. * License as published by the Free Software Foundation; either
  9. * version 2 of the License, or (at your option) any later version.
  10. *
  11. * This library is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * Lesser General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public
  17. * License along with this library; if not, write to the Free Software
  18. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  19. */
  20. #ifdef TARGET_DEFS_ONLY
  21. /* number of available registers */
  22. #define NB_REGS 5
  23. #define NB_ASM_REGS 8
  24. #define CONFIG_TCC_ASM
  25. /* a register can belong to several classes. The classes must be
  26. sorted from more general to more precise (see gv2() code which does
  27. assumptions on it). */
  28. #define RC_INT 0x0001 /* generic integer register */
  29. #define RC_FLOAT 0x0002 /* generic float register */
  30. #define RC_EAX 0x0004
  31. #define RC_ST0 0x0008
  32. #define RC_ECX 0x0010
  33. #define RC_EDX 0x0020
  34. #define RC_EBX 0x0040
  35. #define RC_IRET RC_EAX /* function return: integer register */
  36. #define RC_LRET RC_EDX /* function return: second integer register */
  37. #define RC_FRET RC_ST0 /* function return: float register */
  38. /* pretty names for the registers */
  39. enum {
  40. TREG_EAX = 0,
  41. TREG_ECX,
  42. TREG_EDX,
  43. TREG_EBX,
  44. TREG_ST0,
  45. TREG_ESP = 4
  46. };
  47. /* return registers for function */
  48. #define REG_IRET TREG_EAX /* single word int return register */
  49. #define REG_LRET TREG_EDX /* second word return register (for long long) */
  50. #define REG_FRET TREG_ST0 /* float return register */
  51. /* defined if function parameters must be evaluated in reverse order */
  52. #define INVERT_FUNC_PARAMS
  53. /* defined if structures are passed as pointers. Otherwise structures
  54. are directly pushed on stack. */
  55. /* #define FUNC_STRUCT_PARAM_AS_PTR */
  56. /* pointer size, in bytes */
  57. #define PTR_SIZE 4
  58. /* long double size and alignment, in bytes */
  59. #define LDOUBLE_SIZE 12
  60. #define LDOUBLE_ALIGN 4
  61. /* maximum alignment (for aligned attribute support) */
  62. #define MAX_ALIGN 8
  63. /******************************************************/
  64. #else /* ! TARGET_DEFS_ONLY */
  65. /******************************************************/
  66. #include "tcc.h"
  67. /* define to 1/0 to [not] have EBX as 4th register */
  68. #define USE_EBX 0
  69. ST_DATA const int reg_classes[NB_REGS] = {
  70. /* eax */ RC_INT | RC_EAX,
  71. /* ecx */ RC_INT | RC_ECX,
  72. /* edx */ RC_INT | RC_EDX,
  73. /* ebx */ (RC_INT | RC_EBX) * USE_EBX,
  74. /* st0 */ RC_FLOAT | RC_ST0,
  75. };
  76. static unsigned long func_sub_sp_offset;
  77. static int func_ret_sub;
  78. #ifdef CONFIG_TCC_BCHECK
  79. static addr_t func_bound_offset;
  80. static unsigned long func_bound_ind;
  81. #endif
  82. /* XXX: make it faster ? */
  83. ST_FUNC void g(int c)
  84. {
  85. int ind1;
  86. if (nocode_wanted)
  87. return;
  88. ind1 = ind + 1;
  89. if (ind1 > cur_text_section->data_allocated)
  90. section_realloc(cur_text_section, ind1);
  91. cur_text_section->data[ind] = c;
  92. ind = ind1;
  93. }
  94. ST_FUNC void o(unsigned int c)
  95. {
  96. while (c) {
  97. g(c);
  98. c = c >> 8;
  99. }
  100. }
  101. ST_FUNC void gen_le16(int v)
  102. {
  103. g(v);
  104. g(v >> 8);
  105. }
  106. ST_FUNC void gen_le32(int c)
  107. {
  108. g(c);
  109. g(c >> 8);
  110. g(c >> 16);
  111. g(c >> 24);
  112. }
  113. /* output a symbol and patch all calls to it */
  114. ST_FUNC void gsym_addr(int t, int a)
  115. {
  116. while (t) {
  117. unsigned char *ptr = cur_text_section->data + t;
  118. uint32_t n = read32le(ptr); /* next value */
  119. write32le(ptr, a - t - 4);
  120. t = n;
  121. }
  122. }
  123. ST_FUNC void gsym(int t)
  124. {
  125. gsym_addr(t, ind);
  126. }
  127. /* instruction + 4 bytes data. Return the address of the data */
  128. static int oad(int c, int s)
  129. {
  130. int t;
  131. if (nocode_wanted)
  132. return s;
  133. o(c);
  134. t = ind;
  135. gen_le32(s);
  136. return t;
  137. }
  138. /* generate jmp to a label */
  139. #define gjmp2(instr,lbl) oad(instr,lbl)
  140. /* output constant with relocation if 'r & VT_SYM' is true */
  141. ST_FUNC void gen_addr32(int r, Sym *sym, int c)
  142. {
  143. if (r & VT_SYM)
  144. greloc(cur_text_section, sym, ind, R_386_32);
  145. gen_le32(c);
  146. }
  147. ST_FUNC void gen_addrpc32(int r, Sym *sym, int c)
  148. {
  149. if (r & VT_SYM)
  150. greloc(cur_text_section, sym, ind, R_386_PC32);
  151. gen_le32(c - 4);
  152. }
  153. /* generate a modrm reference. 'op_reg' contains the additional 3
  154. opcode bits */
  155. static void gen_modrm(int op_reg, int r, Sym *sym, int c)
  156. {
  157. op_reg = op_reg << 3;
  158. if ((r & VT_VALMASK) == VT_CONST) {
  159. /* constant memory reference */
  160. o(0x05 | op_reg);
  161. gen_addr32(r, sym, c);
  162. } else if ((r & VT_VALMASK) == VT_LOCAL) {
  163. /* currently, we use only ebp as base */
  164. if (c == (char)c) {
  165. /* short reference */
  166. o(0x45 | op_reg);
  167. g(c);
  168. } else {
  169. oad(0x85 | op_reg, c);
  170. }
  171. } else {
  172. g(0x00 | op_reg | (r & VT_VALMASK));
  173. }
  174. }
  175. /* load 'r' from value 'sv' */
  176. ST_FUNC void load(int r, SValue *sv)
  177. {
  178. int v, t, ft, fc, fr;
  179. SValue v1;
  180. #ifdef TCC_TARGET_PE
  181. SValue v2;
  182. sv = pe_getimport(sv, &v2);
  183. #endif
  184. fr = sv->r;
  185. ft = sv->type.t & ~VT_DEFSIGN;
  186. fc = sv->c.i;
  187. ft &= ~(VT_VOLATILE | VT_CONSTANT);
  188. v = fr & VT_VALMASK;
  189. if (fr & VT_LVAL) {
  190. if (v == VT_LLOCAL) {
  191. v1.type.t = VT_INT;
  192. v1.r = VT_LOCAL | VT_LVAL;
  193. v1.c.i = fc;
  194. fr = r;
  195. if (!(reg_classes[fr] & RC_INT))
  196. fr = get_reg(RC_INT);
  197. load(fr, &v1);
  198. }
  199. if ((ft & VT_BTYPE) == VT_FLOAT) {
  200. o(0xd9); /* flds */
  201. r = 0;
  202. } else if ((ft & VT_BTYPE) == VT_DOUBLE) {
  203. o(0xdd); /* fldl */
  204. r = 0;
  205. } else if ((ft & VT_BTYPE) == VT_LDOUBLE) {
  206. o(0xdb); /* fldt */
  207. r = 5;
  208. } else if ((ft & VT_TYPE) == VT_BYTE || (ft & VT_TYPE) == VT_BOOL) {
  209. o(0xbe0f); /* movsbl */
  210. } else if ((ft & VT_TYPE) == (VT_BYTE | VT_UNSIGNED)) {
  211. o(0xb60f); /* movzbl */
  212. } else if ((ft & VT_TYPE) == VT_SHORT) {
  213. o(0xbf0f); /* movswl */
  214. } else if ((ft & VT_TYPE) == (VT_SHORT | VT_UNSIGNED)) {
  215. o(0xb70f); /* movzwl */
  216. } else {
  217. o(0x8b); /* movl */
  218. }
  219. gen_modrm(r, fr, sv->sym, fc);
  220. } else {
  221. if (v == VT_CONST) {
  222. o(0xb8 + r); /* mov $xx, r */
  223. gen_addr32(fr, sv->sym, fc);
  224. } else if (v == VT_LOCAL) {
  225. if (fc) {
  226. o(0x8d); /* lea xxx(%ebp), r */
  227. gen_modrm(r, VT_LOCAL, sv->sym, fc);
  228. } else {
  229. o(0x89);
  230. o(0xe8 + r); /* mov %ebp, r */
  231. }
  232. } else if (v == VT_CMP) {
  233. oad(0xb8 + r, 0); /* mov $0, r */
  234. o(0x0f); /* setxx %br */
  235. o(fc);
  236. o(0xc0 + r);
  237. } else if (v == VT_JMP || v == VT_JMPI) {
  238. t = v & 1;
  239. oad(0xb8 + r, t); /* mov $1, r */
  240. o(0x05eb); /* jmp after */
  241. gsym(fc);
  242. oad(0xb8 + r, t ^ 1); /* mov $0, r */
  243. } else if (v != r) {
  244. o(0x89);
  245. o(0xc0 + r + v * 8); /* mov v, r */
  246. }
  247. }
  248. }
  249. /* store register 'r' in lvalue 'v' */
  250. ST_FUNC void store(int r, SValue *v)
  251. {
  252. int fr, bt, ft, fc;
  253. #ifdef TCC_TARGET_PE
  254. SValue v2;
  255. v = pe_getimport(v, &v2);
  256. #endif
  257. ft = v->type.t;
  258. fc = v->c.i;
  259. fr = v->r & VT_VALMASK;
  260. ft &= ~(VT_VOLATILE | VT_CONSTANT);
  261. bt = ft & VT_BTYPE;
  262. /* XXX: incorrect if float reg to reg */
  263. if (bt == VT_FLOAT) {
  264. o(0xd9); /* fsts */
  265. r = 2;
  266. } else if (bt == VT_DOUBLE) {
  267. o(0xdd); /* fstpl */
  268. r = 2;
  269. } else if (bt == VT_LDOUBLE) {
  270. o(0xc0d9); /* fld %st(0) */
  271. o(0xdb); /* fstpt */
  272. r = 7;
  273. } else {
  274. if (bt == VT_SHORT)
  275. o(0x66);
  276. if (bt == VT_BYTE || bt == VT_BOOL)
  277. o(0x88);
  278. else
  279. o(0x89);
  280. }
  281. if (fr == VT_CONST ||
  282. fr == VT_LOCAL ||
  283. (v->r & VT_LVAL)) {
  284. gen_modrm(r, v->r, v->sym, fc);
  285. } else if (fr != r) {
  286. o(0xc0 + fr + r * 8); /* mov r, fr */
  287. }
  288. }
  289. static void gadd_sp(int val)
  290. {
  291. if (val == (char)val) {
  292. o(0xc483);
  293. g(val);
  294. } else {
  295. oad(0xc481, val); /* add $xxx, %esp */
  296. }
  297. }
  298. #if defined CONFIG_TCC_BCHECK || defined TCC_TARGET_PE
  299. static void gen_static_call(int v)
  300. {
  301. Sym *sym;
  302. sym = external_global_sym(v, &func_old_type, 0);
  303. oad(0xe8, -4);
  304. greloc(cur_text_section, sym, ind-4, R_386_PC32);
  305. }
  306. #endif
  307. /* 'is_jmp' is '1' if it is a jump */
  308. static void gcall_or_jmp(int is_jmp)
  309. {
  310. int r;
  311. if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST && (vtop->r & VT_SYM)) {
  312. /* constant and relocation case */
  313. greloc(cur_text_section, vtop->sym, ind + 1, R_386_PC32);
  314. oad(0xe8 + is_jmp, vtop->c.i - 4); /* call/jmp im */
  315. } else {
  316. /* otherwise, indirect call */
  317. r = gv(RC_INT);
  318. o(0xff); /* call/jmp *r */
  319. o(0xd0 + r + (is_jmp << 4));
  320. }
  321. if (!is_jmp) {
  322. int rt;
  323. /* extend the return value to the whole register if necessary
  324. visual studio and gcc do not always set the whole eax register
  325. when assigning the return value of a function */
  326. rt = vtop->type.ref->type.t;
  327. switch (rt & VT_BTYPE) {
  328. case VT_BYTE:
  329. if (rt & VT_UNSIGNED) {
  330. o(0xc0b60f); /* movzx %al, %eax */
  331. }
  332. else {
  333. o(0xc0be0f); /* movsx %al, %eax */
  334. }
  335. break;
  336. case VT_SHORT:
  337. if (rt & VT_UNSIGNED) {
  338. o(0xc0b70f); /* movzx %ax, %eax */
  339. }
  340. else {
  341. o(0xc0bf0f); /* movsx %ax, %eax */
  342. }
  343. break;
  344. default:
  345. break;
  346. }
  347. }
  348. }
  349. static uint8_t fastcall_regs[3] = { TREG_EAX, TREG_EDX, TREG_ECX };
  350. static uint8_t fastcallw_regs[2] = { TREG_ECX, TREG_EDX };
  351. /* Return the number of registers needed to return the struct, or 0 if
  352. returning via struct pointer. */
  353. ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret, int *ret_align, int *regsize)
  354. {
  355. #ifdef TCC_TARGET_PE
  356. int size, align;
  357. *ret_align = 1; // Never have to re-align return values for x86
  358. *regsize = 4;
  359. size = type_size(vt, &align);
  360. if (size > 8 || (size & (size - 1)))
  361. return 0;
  362. if (size == 8)
  363. ret->t = VT_LLONG;
  364. else if (size == 4)
  365. ret->t = VT_INT;
  366. else if (size == 2)
  367. ret->t = VT_SHORT;
  368. else
  369. ret->t = VT_BYTE;
  370. ret->ref = NULL;
  371. return 1;
  372. #else
  373. *ret_align = 1; // Never have to re-align return values for x86
  374. return 0;
  375. #endif
  376. }
  377. /* Generate function call. The function address is pushed first, then
  378. all the parameters in call order. This functions pops all the
  379. parameters and the function address. */
  380. ST_FUNC void gfunc_call(int nb_args)
  381. {
  382. int size, align, r, args_size, i, func_call;
  383. Sym *func_sym;
  384. args_size = 0;
  385. for(i = 0;i < nb_args; i++) {
  386. if ((vtop->type.t & VT_BTYPE) == VT_STRUCT) {
  387. size = type_size(&vtop->type, &align);
  388. /* align to stack align size */
  389. size = (size + 3) & ~3;
  390. /* allocate the necessary size on stack */
  391. oad(0xec81, size); /* sub $xxx, %esp */
  392. /* generate structure store */
  393. r = get_reg(RC_INT);
  394. o(0x89); /* mov %esp, r */
  395. o(0xe0 + r);
  396. vset(&vtop->type, r | VT_LVAL, 0);
  397. vswap();
  398. vstore();
  399. args_size += size;
  400. } else if (is_float(vtop->type.t)) {
  401. gv(RC_FLOAT); /* only one float register */
  402. if ((vtop->type.t & VT_BTYPE) == VT_FLOAT)
  403. size = 4;
  404. else if ((vtop->type.t & VT_BTYPE) == VT_DOUBLE)
  405. size = 8;
  406. else
  407. size = 12;
  408. oad(0xec81, size); /* sub $xxx, %esp */
  409. if (size == 12)
  410. o(0x7cdb);
  411. else
  412. o(0x5cd9 + size - 4); /* fstp[s|l] 0(%esp) */
  413. g(0x24);
  414. g(0x00);
  415. args_size += size;
  416. } else {
  417. /* simple type (currently always same size) */
  418. /* XXX: implicit cast ? */
  419. r = gv(RC_INT);
  420. if ((vtop->type.t & VT_BTYPE) == VT_LLONG) {
  421. size = 8;
  422. o(0x50 + vtop->r2); /* push r */
  423. } else {
  424. size = 4;
  425. }
  426. o(0x50 + r); /* push r */
  427. args_size += size;
  428. }
  429. vtop--;
  430. }
  431. save_regs(0); /* save used temporary registers */
  432. func_sym = vtop->type.ref;
  433. func_call = func_sym->f.func_call;
  434. /* fast call case */
  435. if ((func_call >= FUNC_FASTCALL1 && func_call <= FUNC_FASTCALL3) ||
  436. func_call == FUNC_FASTCALLW) {
  437. int fastcall_nb_regs;
  438. uint8_t *fastcall_regs_ptr;
  439. if (func_call == FUNC_FASTCALLW) {
  440. fastcall_regs_ptr = fastcallw_regs;
  441. fastcall_nb_regs = 2;
  442. } else {
  443. fastcall_regs_ptr = fastcall_regs;
  444. fastcall_nb_regs = func_call - FUNC_FASTCALL1 + 1;
  445. }
  446. for(i = 0;i < fastcall_nb_regs; i++) {
  447. if (args_size <= 0)
  448. break;
  449. o(0x58 + fastcall_regs_ptr[i]); /* pop r */
  450. /* XXX: incorrect for struct/floats */
  451. args_size -= 4;
  452. }
  453. }
  454. #ifndef TCC_TARGET_PE
  455. else if ((vtop->type.ref->type.t & VT_BTYPE) == VT_STRUCT)
  456. args_size -= 4;
  457. #endif
  458. gcall_or_jmp(0);
  459. if (args_size && func_call != FUNC_STDCALL && func_call != FUNC_FASTCALLW)
  460. gadd_sp(args_size);
  461. vtop--;
  462. }
  463. #ifdef TCC_TARGET_PE
  464. #define FUNC_PROLOG_SIZE (10 + USE_EBX)
  465. #else
  466. #define FUNC_PROLOG_SIZE (9 + USE_EBX)
  467. #endif
  468. /* generate function prolog of type 't' */
  469. ST_FUNC void gfunc_prolog(CType *func_type)
  470. {
  471. int addr, align, size, func_call, fastcall_nb_regs;
  472. int param_index, param_addr;
  473. uint8_t *fastcall_regs_ptr;
  474. Sym *sym;
  475. CType *type;
  476. sym = func_type->ref;
  477. func_call = sym->f.func_call;
  478. addr = 8;
  479. loc = 0;
  480. func_vc = 0;
  481. if (func_call >= FUNC_FASTCALL1 && func_call <= FUNC_FASTCALL3) {
  482. fastcall_nb_regs = func_call - FUNC_FASTCALL1 + 1;
  483. fastcall_regs_ptr = fastcall_regs;
  484. } else if (func_call == FUNC_FASTCALLW) {
  485. fastcall_nb_regs = 2;
  486. fastcall_regs_ptr = fastcallw_regs;
  487. } else {
  488. fastcall_nb_regs = 0;
  489. fastcall_regs_ptr = NULL;
  490. }
  491. param_index = 0;
  492. ind += FUNC_PROLOG_SIZE;
  493. func_sub_sp_offset = ind;
  494. /* if the function returns a structure, then add an
  495. implicit pointer parameter */
  496. func_vt = sym->type;
  497. func_var = (sym->f.func_type == FUNC_ELLIPSIS);
  498. #ifdef TCC_TARGET_PE
  499. size = type_size(&func_vt,&align);
  500. if (((func_vt.t & VT_BTYPE) == VT_STRUCT)
  501. && (size > 8 || (size & (size - 1)))) {
  502. #else
  503. if ((func_vt.t & VT_BTYPE) == VT_STRUCT) {
  504. #endif
  505. /* XXX: fastcall case ? */
  506. func_vc = addr;
  507. addr += 4;
  508. param_index++;
  509. }
  510. /* define parameters */
  511. while ((sym = sym->next) != NULL) {
  512. type = &sym->type;
  513. size = type_size(type, &align);
  514. size = (size + 3) & ~3;
  515. #ifdef FUNC_STRUCT_PARAM_AS_PTR
  516. /* structs are passed as pointer */
  517. if ((type->t & VT_BTYPE) == VT_STRUCT) {
  518. size = 4;
  519. }
  520. #endif
  521. if (param_index < fastcall_nb_regs) {
  522. /* save FASTCALL register */
  523. loc -= 4;
  524. o(0x89); /* movl */
  525. gen_modrm(fastcall_regs_ptr[param_index], VT_LOCAL, NULL, loc);
  526. param_addr = loc;
  527. } else {
  528. param_addr = addr;
  529. addr += size;
  530. }
  531. sym_push(sym->v & ~SYM_FIELD, type,
  532. VT_LOCAL | lvalue_type(type->t), param_addr);
  533. param_index++;
  534. }
  535. func_ret_sub = 0;
  536. /* pascal type call or fastcall ? */
  537. if (func_call == FUNC_STDCALL || func_call == FUNC_FASTCALLW)
  538. func_ret_sub = addr - 8;
  539. #ifndef TCC_TARGET_PE
  540. else if (func_vc)
  541. func_ret_sub = 4;
  542. #endif
  543. #ifdef CONFIG_TCC_BCHECK
  544. /* leave some room for bound checking code */
  545. if (tcc_state->do_bounds_check) {
  546. func_bound_offset = lbounds_section->data_offset;
  547. func_bound_ind = ind;
  548. oad(0xb8, 0); /* lbound section pointer */
  549. oad(0xb8, 0); /* call to function */
  550. }
  551. #endif
  552. }
  553. /* generate function epilog */
  554. ST_FUNC void gfunc_epilog(void)
  555. {
  556. addr_t v, saved_ind;
  557. #ifdef CONFIG_TCC_BCHECK
  558. if (tcc_state->do_bounds_check
  559. && func_bound_offset != lbounds_section->data_offset) {
  560. addr_t saved_ind;
  561. addr_t *bounds_ptr;
  562. Sym *sym_data;
  563. /* add end of table info */
  564. bounds_ptr = section_ptr_add(lbounds_section, sizeof(addr_t));
  565. *bounds_ptr = 0;
  566. /* generate bound local allocation */
  567. saved_ind = ind;
  568. ind = func_bound_ind;
  569. sym_data = get_sym_ref(&char_pointer_type, lbounds_section,
  570. func_bound_offset, lbounds_section->data_offset);
  571. greloc(cur_text_section, sym_data,
  572. ind + 1, R_386_32);
  573. oad(0xb8, 0); /* mov %eax, xxx */
  574. gen_static_call(TOK___bound_local_new);
  575. ind = saved_ind;
  576. /* generate bound check local freeing */
  577. o(0x5250); /* save returned value, if any */
  578. greloc(cur_text_section, sym_data, ind + 1, R_386_32);
  579. oad(0xb8, 0); /* mov %eax, xxx */
  580. gen_static_call(TOK___bound_local_delete);
  581. o(0x585a); /* restore returned value, if any */
  582. }
  583. #endif
  584. /* align local size to word & save local variables */
  585. v = (-loc + 3) & -4;
  586. #if USE_EBX
  587. o(0x8b);
  588. gen_modrm(TREG_EBX, VT_LOCAL, NULL, -(v+4));
  589. #endif
  590. o(0xc9); /* leave */
  591. if (func_ret_sub == 0) {
  592. o(0xc3); /* ret */
  593. } else {
  594. o(0xc2); /* ret n */
  595. g(func_ret_sub);
  596. g(func_ret_sub >> 8);
  597. }
  598. saved_ind = ind;
  599. ind = func_sub_sp_offset - FUNC_PROLOG_SIZE;
  600. #ifdef TCC_TARGET_PE
  601. if (v >= 4096) {
  602. oad(0xb8, v); /* mov stacksize, %eax */
  603. gen_static_call(TOK___chkstk); /* call __chkstk, (does the stackframe too) */
  604. } else
  605. #endif
  606. {
  607. o(0xe58955); /* push %ebp, mov %esp, %ebp */
  608. o(0xec81); /* sub esp, stacksize */
  609. gen_le32(v);
  610. #ifdef TCC_TARGET_PE
  611. o(0x90); /* adjust to FUNC_PROLOG_SIZE */
  612. #endif
  613. }
  614. o(0x53 * USE_EBX); /* push ebx */
  615. ind = saved_ind;
  616. }
  617. /* generate a jump to a label */
  618. ST_FUNC int gjmp(int t)
  619. {
  620. return gjmp2(0xe9, t);
  621. }
  622. /* generate a jump to a fixed address */
  623. ST_FUNC void gjmp_addr(int a)
  624. {
  625. int r;
  626. r = a - ind - 2;
  627. if (r == (char)r) {
  628. g(0xeb);
  629. g(r);
  630. } else {
  631. oad(0xe9, a - ind - 5);
  632. }
  633. }
  634. ST_FUNC void gtst_addr(int inv, int a)
  635. {
  636. int v = vtop->r & VT_VALMASK;
  637. if (v == VT_CMP) {
  638. inv ^= (vtop--)->c.i;
  639. a -= ind + 2;
  640. if (a == (char)a) {
  641. g(inv - 32);
  642. g(a);
  643. } else {
  644. g(0x0f);
  645. oad(inv - 16, a - 4);
  646. }
  647. } else if ((v & ~1) == VT_JMP) {
  648. if ((v & 1) != inv) {
  649. gjmp_addr(a);
  650. gsym(vtop->c.i);
  651. } else {
  652. gsym(vtop->c.i);
  653. o(0x05eb);
  654. gjmp_addr(a);
  655. }
  656. vtop--;
  657. }
  658. }
  659. /* generate a test. set 'inv' to invert test. Stack entry is popped */
  660. ST_FUNC int gtst(int inv, int t)
  661. {
  662. int v = vtop->r & VT_VALMASK;
  663. if (nocode_wanted) {
  664. ;
  665. } else if (v == VT_CMP) {
  666. /* fast case : can jump directly since flags are set */
  667. g(0x0f);
  668. t = gjmp2((vtop->c.i - 16) ^ inv, t);
  669. } else if (v == VT_JMP || v == VT_JMPI) {
  670. /* && or || optimization */
  671. if ((v & 1) == inv) {
  672. /* insert vtop->c jump list in t */
  673. uint32_t n1, n = vtop->c.i;
  674. if (n) {
  675. while ((n1 = read32le(cur_text_section->data + n)))
  676. n = n1;
  677. write32le(cur_text_section->data + n, t);
  678. t = vtop->c.i;
  679. }
  680. } else {
  681. t = gjmp(t);
  682. gsym(vtop->c.i);
  683. }
  684. }
  685. vtop--;
  686. return t;
  687. }
  688. /* generate an integer binary operation */
  689. ST_FUNC void gen_opi(int op)
  690. {
  691. int r, fr, opc, c;
  692. switch(op) {
  693. case '+':
  694. case TOK_ADDC1: /* add with carry generation */
  695. opc = 0;
  696. gen_op8:
  697. if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
  698. /* constant case */
  699. vswap();
  700. r = gv(RC_INT);
  701. vswap();
  702. c = vtop->c.i;
  703. if (c == (char)c) {
  704. /* generate inc and dec for smaller code */
  705. if (c==1 && opc==0 && op != TOK_ADDC1) {
  706. o (0x40 | r); // inc
  707. } else if (c==1 && opc==5 && op != TOK_SUBC1) {
  708. o (0x48 | r); // dec
  709. } else {
  710. o(0x83);
  711. o(0xc0 | (opc << 3) | r);
  712. g(c);
  713. }
  714. } else {
  715. o(0x81);
  716. oad(0xc0 | (opc << 3) | r, c);
  717. }
  718. } else {
  719. gv2(RC_INT, RC_INT);
  720. r = vtop[-1].r;
  721. fr = vtop[0].r;
  722. o((opc << 3) | 0x01);
  723. o(0xc0 + r + fr * 8);
  724. }
  725. vtop--;
  726. if (op >= TOK_ULT && op <= TOK_GT) {
  727. vtop->r = VT_CMP;
  728. vtop->c.i = op;
  729. }
  730. break;
  731. case '-':
  732. case TOK_SUBC1: /* sub with carry generation */
  733. opc = 5;
  734. goto gen_op8;
  735. case TOK_ADDC2: /* add with carry use */
  736. opc = 2;
  737. goto gen_op8;
  738. case TOK_SUBC2: /* sub with carry use */
  739. opc = 3;
  740. goto gen_op8;
  741. case '&':
  742. opc = 4;
  743. goto gen_op8;
  744. case '^':
  745. opc = 6;
  746. goto gen_op8;
  747. case '|':
  748. opc = 1;
  749. goto gen_op8;
  750. case '*':
  751. gv2(RC_INT, RC_INT);
  752. r = vtop[-1].r;
  753. fr = vtop[0].r;
  754. vtop--;
  755. o(0xaf0f); /* imul fr, r */
  756. o(0xc0 + fr + r * 8);
  757. break;
  758. case TOK_SHL:
  759. opc = 4;
  760. goto gen_shift;
  761. case TOK_SHR:
  762. opc = 5;
  763. goto gen_shift;
  764. case TOK_SAR:
  765. opc = 7;
  766. gen_shift:
  767. opc = 0xc0 | (opc << 3);
  768. if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
  769. /* constant case */
  770. vswap();
  771. r = gv(RC_INT);
  772. vswap();
  773. c = vtop->c.i & 0x1f;
  774. o(0xc1); /* shl/shr/sar $xxx, r */
  775. o(opc | r);
  776. g(c);
  777. } else {
  778. /* we generate the shift in ecx */
  779. gv2(RC_INT, RC_ECX);
  780. r = vtop[-1].r;
  781. o(0xd3); /* shl/shr/sar %cl, r */
  782. o(opc | r);
  783. }
  784. vtop--;
  785. break;
  786. case '/':
  787. case TOK_UDIV:
  788. case TOK_PDIV:
  789. case '%':
  790. case TOK_UMOD:
  791. case TOK_UMULL:
  792. /* first operand must be in eax */
  793. /* XXX: need better constraint for second operand */
  794. gv2(RC_EAX, RC_ECX);
  795. r = vtop[-1].r;
  796. fr = vtop[0].r;
  797. vtop--;
  798. save_reg(TREG_EDX);
  799. /* save EAX too if used otherwise */
  800. save_reg_upstack(TREG_EAX, 1);
  801. if (op == TOK_UMULL) {
  802. o(0xf7); /* mul fr */
  803. o(0xe0 + fr);
  804. vtop->r2 = TREG_EDX;
  805. r = TREG_EAX;
  806. } else {
  807. if (op == TOK_UDIV || op == TOK_UMOD) {
  808. o(0xf7d231); /* xor %edx, %edx, div fr, %eax */
  809. o(0xf0 + fr);
  810. } else {
  811. o(0xf799); /* cltd, idiv fr, %eax */
  812. o(0xf8 + fr);
  813. }
  814. if (op == '%' || op == TOK_UMOD)
  815. r = TREG_EDX;
  816. else
  817. r = TREG_EAX;
  818. }
  819. vtop->r = r;
  820. break;
  821. default:
  822. opc = 7;
  823. goto gen_op8;
  824. }
  825. }
  826. /* generate a floating point operation 'v = t1 op t2' instruction. The
  827. two operands are guaranteed to have the same floating point type */
  828. /* XXX: need to use ST1 too */
  829. ST_FUNC void gen_opf(int op)
  830. {
  831. int a, ft, fc, swapped, r;
  832. /* convert constants to memory references */
  833. if ((vtop[-1].r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
  834. vswap();
  835. gv(RC_FLOAT);
  836. vswap();
  837. }
  838. if ((vtop[0].r & (VT_VALMASK | VT_LVAL)) == VT_CONST)
  839. gv(RC_FLOAT);
  840. /* must put at least one value in the floating point register */
  841. if ((vtop[-1].r & VT_LVAL) &&
  842. (vtop[0].r & VT_LVAL)) {
  843. vswap();
  844. gv(RC_FLOAT);
  845. vswap();
  846. }
  847. swapped = 0;
  848. /* swap the stack if needed so that t1 is the register and t2 is
  849. the memory reference */
  850. if (vtop[-1].r & VT_LVAL) {
  851. vswap();
  852. swapped = 1;
  853. }
  854. if (op >= TOK_ULT && op <= TOK_GT) {
  855. /* load on stack second operand */
  856. load(TREG_ST0, vtop);
  857. save_reg(TREG_EAX); /* eax is used by FP comparison code */
  858. if (op == TOK_GE || op == TOK_GT)
  859. swapped = !swapped;
  860. else if (op == TOK_EQ || op == TOK_NE)
  861. swapped = 0;
  862. if (swapped)
  863. o(0xc9d9); /* fxch %st(1) */
  864. if (op == TOK_EQ || op == TOK_NE)
  865. o(0xe9da); /* fucompp */
  866. else
  867. o(0xd9de); /* fcompp */
  868. o(0xe0df); /* fnstsw %ax */
  869. if (op == TOK_EQ) {
  870. o(0x45e480); /* and $0x45, %ah */
  871. o(0x40fC80); /* cmp $0x40, %ah */
  872. } else if (op == TOK_NE) {
  873. o(0x45e480); /* and $0x45, %ah */
  874. o(0x40f480); /* xor $0x40, %ah */
  875. op = TOK_NE;
  876. } else if (op == TOK_GE || op == TOK_LE) {
  877. o(0x05c4f6); /* test $0x05, %ah */
  878. op = TOK_EQ;
  879. } else {
  880. o(0x45c4f6); /* test $0x45, %ah */
  881. op = TOK_EQ;
  882. }
  883. vtop--;
  884. vtop->r = VT_CMP;
  885. vtop->c.i = op;
  886. } else {
  887. /* no memory reference possible for long double operations */
  888. if ((vtop->type.t & VT_BTYPE) == VT_LDOUBLE) {
  889. load(TREG_ST0, vtop);
  890. swapped = !swapped;
  891. }
  892. switch(op) {
  893. default:
  894. case '+':
  895. a = 0;
  896. break;
  897. case '-':
  898. a = 4;
  899. if (swapped)
  900. a++;
  901. break;
  902. case '*':
  903. a = 1;
  904. break;
  905. case '/':
  906. a = 6;
  907. if (swapped)
  908. a++;
  909. break;
  910. }
  911. ft = vtop->type.t;
  912. fc = vtop->c.i;
  913. if ((ft & VT_BTYPE) == VT_LDOUBLE) {
  914. o(0xde); /* fxxxp %st, %st(1) */
  915. o(0xc1 + (a << 3));
  916. } else {
  917. /* if saved lvalue, then we must reload it */
  918. r = vtop->r;
  919. if ((r & VT_VALMASK) == VT_LLOCAL) {
  920. SValue v1;
  921. r = get_reg(RC_INT);
  922. v1.type.t = VT_INT;
  923. v1.r = VT_LOCAL | VT_LVAL;
  924. v1.c.i = fc;
  925. load(r, &v1);
  926. fc = 0;
  927. }
  928. if ((ft & VT_BTYPE) == VT_DOUBLE)
  929. o(0xdc);
  930. else
  931. o(0xd8);
  932. gen_modrm(a, r, vtop->sym, fc);
  933. }
  934. vtop--;
  935. }
  936. }
  937. /* convert integers to fp 't' type. Must handle 'int', 'unsigned int'
  938. and 'long long' cases. */
  939. ST_FUNC void gen_cvt_itof(int t)
  940. {
  941. save_reg(TREG_ST0);
  942. gv(RC_INT);
  943. if ((vtop->type.t & VT_BTYPE) == VT_LLONG) {
  944. /* signed long long to float/double/long double (unsigned case
  945. is handled generically) */
  946. o(0x50 + vtop->r2); /* push r2 */
  947. o(0x50 + (vtop->r & VT_VALMASK)); /* push r */
  948. o(0x242cdf); /* fildll (%esp) */
  949. o(0x08c483); /* add $8, %esp */
  950. } else if ((vtop->type.t & (VT_BTYPE | VT_UNSIGNED)) ==
  951. (VT_INT | VT_UNSIGNED)) {
  952. /* unsigned int to float/double/long double */
  953. o(0x6a); /* push $0 */
  954. g(0x00);
  955. o(0x50 + (vtop->r & VT_VALMASK)); /* push r */
  956. o(0x242cdf); /* fildll (%esp) */
  957. o(0x08c483); /* add $8, %esp */
  958. } else {
  959. /* int to float/double/long double */
  960. o(0x50 + (vtop->r & VT_VALMASK)); /* push r */
  961. o(0x2404db); /* fildl (%esp) */
  962. o(0x04c483); /* add $4, %esp */
  963. }
  964. vtop->r = TREG_ST0;
  965. }
  966. /* convert fp to int 't' type */
  967. ST_FUNC void gen_cvt_ftoi(int t)
  968. {
  969. int bt = vtop->type.t & VT_BTYPE;
  970. if (bt == VT_FLOAT)
  971. vpush_global_sym(&func_old_type, TOK___fixsfdi);
  972. else if (bt == VT_LDOUBLE)
  973. vpush_global_sym(&func_old_type, TOK___fixxfdi);
  974. else
  975. vpush_global_sym(&func_old_type, TOK___fixdfdi);
  976. vswap();
  977. gfunc_call(1);
  978. vpushi(0);
  979. vtop->r = REG_IRET;
  980. vtop->r2 = REG_LRET;
  981. }
  982. /* convert from one floating point type to another */
  983. ST_FUNC void gen_cvt_ftof(int t)
  984. {
  985. /* all we have to do on i386 is to put the float in a register */
  986. gv(RC_FLOAT);
  987. }
  988. /* computed goto support */
  989. ST_FUNC void ggoto(void)
  990. {
  991. gcall_or_jmp(1);
  992. vtop--;
  993. }
  994. /* bound check support functions */
  995. #ifdef CONFIG_TCC_BCHECK
  996. /* generate a bounded pointer addition */
  997. ST_FUNC void gen_bounded_ptr_add(void)
  998. {
  999. /* prepare fast i386 function call (args in eax and edx) */
  1000. gv2(RC_EAX, RC_EDX);
  1001. /* save all temporary registers */
  1002. vtop -= 2;
  1003. save_regs(0);
  1004. /* do a fast function call */
  1005. gen_static_call(TOK___bound_ptr_add);
  1006. /* returned pointer is in eax */
  1007. vtop++;
  1008. vtop->r = TREG_EAX | VT_BOUNDED;
  1009. /* address of bounding function call point */
  1010. vtop->c.i = (cur_text_section->reloc->data_offset - sizeof(Elf32_Rel));
  1011. }
  1012. /* patch pointer addition in vtop so that pointer dereferencing is
  1013. also tested */
  1014. ST_FUNC void gen_bounded_ptr_deref(void)
  1015. {
  1016. addr_t func;
  1017. int size, align;
  1018. Elf32_Rel *rel;
  1019. Sym *sym;
  1020. size = 0;
  1021. /* XXX: put that code in generic part of tcc */
  1022. if (!is_float(vtop->type.t)) {
  1023. if (vtop->r & VT_LVAL_BYTE)
  1024. size = 1;
  1025. else if (vtop->r & VT_LVAL_SHORT)
  1026. size = 2;
  1027. }
  1028. if (!size)
  1029. size = type_size(&vtop->type, &align);
  1030. switch(size) {
  1031. case 1: func = TOK___bound_ptr_indir1; break;
  1032. case 2: func = TOK___bound_ptr_indir2; break;
  1033. case 4: func = TOK___bound_ptr_indir4; break;
  1034. case 8: func = TOK___bound_ptr_indir8; break;
  1035. case 12: func = TOK___bound_ptr_indir12; break;
  1036. case 16: func = TOK___bound_ptr_indir16; break;
  1037. default:
  1038. tcc_error("unhandled size when dereferencing bounded pointer");
  1039. func = 0;
  1040. break;
  1041. }
  1042. /* patch relocation */
  1043. /* XXX: find a better solution ? */
  1044. rel = (Elf32_Rel *)(cur_text_section->reloc->data + vtop->c.i);
  1045. sym = external_global_sym(func, &func_old_type, 0);
  1046. if (!sym->c)
  1047. put_extern_sym(sym, NULL, 0, 0);
  1048. rel->r_info = ELF32_R_INFO(sym->c, ELF32_R_TYPE(rel->r_info));
  1049. }
  1050. #endif
  1051. /* Save the stack pointer onto the stack */
  1052. ST_FUNC void gen_vla_sp_save(int addr) {
  1053. /* mov %esp,addr(%ebp)*/
  1054. o(0x89);
  1055. gen_modrm(TREG_ESP, VT_LOCAL, NULL, addr);
  1056. }
  1057. /* Restore the SP from a location on the stack */
  1058. ST_FUNC void gen_vla_sp_restore(int addr) {
  1059. o(0x8b);
  1060. gen_modrm(TREG_ESP, VT_LOCAL, NULL, addr);
  1061. }
  1062. /* Subtract from the stack pointer, and push the resulting value onto the stack */
  1063. ST_FUNC void gen_vla_alloc(CType *type, int align) {
  1064. #ifdef TCC_TARGET_PE
  1065. /* alloca does more than just adjust %rsp on Windows */
  1066. vpush_global_sym(&func_old_type, TOK_alloca);
  1067. vswap(); /* Move alloca ref past allocation size */
  1068. gfunc_call(1);
  1069. #else
  1070. int r;
  1071. r = gv(RC_INT); /* allocation size */
  1072. /* sub r,%rsp */
  1073. o(0x2b);
  1074. o(0xe0 | r);
  1075. /* We align to 16 bytes rather than align */
  1076. /* and ~15, %esp */
  1077. o(0xf0e483);
  1078. vpop();
  1079. #endif
  1080. }
  1081. /* end of X86 code generator */
  1082. /*************************************************************/
  1083. #endif
  1084. /*************************************************************/