i386-gen.c 28 KB

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