PageRenderTime 121ms CodeModel.GetById 30ms RepoModel.GetById 1ms app.codeStats 0ms

/opengles/src/codegen/emit.c

http://ftk.googlecode.com/
C | 2481 lines | 1798 code | 501 blank | 182 comment | 261 complexity | 16e769e3fd8a62860ea5fbab505fb4b5 MD5 | raw file
Possible License(s): LGPL-3.0
  1. /****************************************************************************/
  2. /* */
  3. /* Copyright (c) 2004, Hans-Martin Will. All rights reserved. */
  4. /* */
  5. /* Redistribution and use in source and binary forms, with or without */
  6. /* modification, are permitted provided that the following conditions are */
  7. /* met: */
  8. /* */
  9. /* * Redistributions of source code must retain the above copyright */
  10. /* notice, this list of conditions and the following disclaimer. */
  11. /* */
  12. /* * Redistributions in binary form must reproduce the above copyright */
  13. /* notice, this list of conditions and the following disclaimer in the */
  14. /* documentation and/or other materials provided with the distribution. */
  15. /* */
  16. /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */
  17. /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */
  18. /* LIMITED TO, THEIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A */
  19. /* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER */
  20. /* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, */
  21. /* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, */
  22. /* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR */
  23. /* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF */
  24. /* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */
  25. /* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */
  26. /* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
  27. /* */
  28. /****************************************************************************/
  29. #include "emit.h"
  30. #include "bitset.h"
  31. #include "heap.h"
  32. #include "segment.h"
  33. #include "arm-codegen.h"
  34. #define SAVE_AREA_SIZE (10 * sizeof(U32)) /* this really depends on the function prolog */
  35. typedef struct reference_t
  36. {
  37. struct reference_t * next;
  38. cg_reference_type_t ref_type;
  39. size_t offset;
  40. }
  41. reference_t;
  42. struct cg_label_t
  43. {
  44. cg_label_t * next;
  45. reference_t * refs;
  46. size_t offset;
  47. };
  48. typedef enum physical_reg_status_t
  49. {
  50. reg_status_init,
  51. reg_status_free,
  52. reg_status_allocated,
  53. reg_status_defined,
  54. reg_status_dirty,
  55. reg_status_secondary
  56. }
  57. physical_reg_status_t;
  58. typedef enum physical_reg_event_t
  59. {
  60. reg_event_init,
  61. reg_event_allocate,
  62. reg_event_deallocate,
  63. reg_event_load,
  64. reg_event_save,
  65. reg_event_define,
  66. reg_event_reassign
  67. }
  68. physical_reg_event_t;
  69. /****************************************************************************/
  70. /* This method implements the finite state machine underlying physical */
  71. /* register allocation. */
  72. /****************************************************************************/
  73. static physical_reg_status_t update_register_status(physical_reg_status_t state,
  74. physical_reg_event_t event)
  75. {
  76. if (event == reg_event_init)
  77. {
  78. return reg_status_init;
  79. }
  80. switch (state)
  81. {
  82. case reg_status_init:
  83. switch (event)
  84. {
  85. case (reg_event_init):
  86. return reg_status_free;
  87. default:
  88. assert(0);
  89. }
  90. break;
  91. case reg_status_free:
  92. switch (event)
  93. {
  94. case (reg_event_allocate):
  95. return reg_status_allocated;
  96. default:
  97. assert(0);
  98. }
  99. break;
  100. case reg_status_allocated:
  101. switch (event)
  102. {
  103. case reg_event_load:
  104. return reg_status_defined;
  105. case reg_event_define:
  106. return reg_status_dirty;
  107. default:
  108. assert(0);
  109. }
  110. break;
  111. case reg_status_defined:
  112. switch (event)
  113. {
  114. case reg_event_deallocate:
  115. return reg_status_free;
  116. case reg_event_reassign:
  117. return reg_status_secondary;
  118. default:
  119. assert(0);
  120. }
  121. break;
  122. case reg_status_dirty:
  123. switch (event)
  124. {
  125. case reg_event_save:
  126. return reg_status_defined;
  127. default:
  128. assert(0);
  129. }
  130. break;
  131. case reg_status_secondary:
  132. switch (event)
  133. {
  134. case reg_event_define:
  135. return reg_status_dirty;
  136. case reg_event_reassign:
  137. return reg_status_defined;
  138. default:
  139. assert(0);
  140. }
  141. break;
  142. default:
  143. assert(0);
  144. break;
  145. }
  146. return reg_status_init;
  147. }
  148. struct physical_reg_list_t;
  149. typedef struct cg_physical_reg_t
  150. {
  151. struct cg_physical_reg_t * prev; /* for LRU chain */
  152. struct cg_physical_reg_t * next; /* for LRU chain */
  153. struct physical_reg_list_t * list;
  154. ARMReg regno; /* physical register */
  155. cg_virtual_reg_t * virtual_reg; /* assigned virtual reg. */
  156. cg_inst_t * next_use; /* next use of ass. value */
  157. physical_reg_status_t state; /* current register state */
  158. int dirty: 1;
  159. int defined:1;
  160. }
  161. cg_physical_reg_t;
  162. typedef struct physical_reg_list_t
  163. {
  164. cg_physical_reg_t * head;
  165. cg_physical_reg_t * tail;
  166. }
  167. physical_reg_list_t;
  168. void reg_list_add(physical_reg_list_t * list, cg_physical_reg_t * reg)
  169. {
  170. assert(!reg->list);
  171. assert(!reg->prev);
  172. assert(!reg->next);
  173. if (list->tail == (cg_physical_reg_t *) 0)
  174. {
  175. assert(list->head == (cg_physical_reg_t *) 0);
  176. list->head = list->tail = reg;
  177. reg->prev = reg->next = NULL;
  178. }
  179. else
  180. {
  181. assert(list->head != (cg_physical_reg_t *) 0);
  182. reg->prev = NULL;
  183. reg->next = list->head;
  184. list->head->prev = reg;
  185. list->head = reg;
  186. }
  187. reg->list = list;
  188. }
  189. void reg_list_remove(physical_reg_list_t * list, cg_physical_reg_t * reg)
  190. {
  191. assert(reg->list == list);
  192. if (reg->prev != (cg_physical_reg_t *) 0)
  193. {
  194. assert(list->head != reg);
  195. reg->prev->next = reg->next;
  196. }
  197. else
  198. {
  199. assert(list->head == reg);
  200. list->head = reg->next;
  201. }
  202. if (reg->next != (cg_physical_reg_t *) 0)
  203. {
  204. assert(list->tail != reg);
  205. reg->next->prev = reg->prev;
  206. }
  207. else
  208. {
  209. assert(list->tail == reg);
  210. list->tail = reg->prev;
  211. }
  212. reg->prev = reg->next = (cg_physical_reg_t *) 0;
  213. reg->list = NULL;
  214. }
  215. void reg_list_move_to_front(physical_reg_list_t * list, cg_physical_reg_t * reg)
  216. {
  217. reg_list_remove(list, reg);
  218. reg_list_add(list, reg);
  219. }
  220. typedef struct literal_t
  221. {
  222. struct literal_t * next;
  223. U32 value;
  224. size_t offset;
  225. }
  226. literal_t;
  227. #define PHYSICAL_REGISTERS (ARMREG_MAX + 1)
  228. struct cg_codegen_t
  229. {
  230. cg_runtime_info_t * runtime;
  231. cg_processor_info_t * processor;
  232. cg_heap_t * heap;
  233. cg_label_t * labels;
  234. cg_segment_t * cseg;
  235. cg_physical_reg_t registers[PHYSICAL_REGISTERS];
  236. cg_physical_reg_t flags;
  237. physical_reg_list_t free_regs; /* phys regs free */
  238. physical_reg_list_t used_regs; /* phys regs in use */
  239. physical_reg_list_t global_regs; /* global phys regs in use */
  240. /************************************************************************/
  241. /* for each block, the following array will be heads to the use chains */
  242. /* within the block currently processed. */
  243. /************************************************************************/
  244. cg_block_t * current_block;
  245. literal_t * literals;
  246. cg_label_t * literal_base;
  247. size_t literal_pool_size;
  248. size_t locals_size_offset;
  249. cg_inst_list_t ** use_chains;
  250. };
  251. int is_simple_inst(cg_inst_t * inst) {
  252. switch (inst->base.opcode)
  253. {
  254. case cg_op_finv:
  255. case cg_op_fdiv:
  256. case cg_op_fsqrt:
  257. case cg_op_div:
  258. case cg_op_mod:
  259. case cg_op_call:
  260. return 0;
  261. default:
  262. return 1;
  263. }
  264. }
  265. size_t cg_codegen_emit_literal(cg_codegen_t * gen, U32 value, int distinct)
  266. {
  267. literal_t ** literal;
  268. for (literal = &gen->literals; (*literal) != (literal_t *) 0; literal = &(*literal)->next)
  269. {
  270. if (!distinct && (*literal)->value == value)
  271. return (*literal)->offset;
  272. }
  273. *literal = cg_heap_allocate(gen->heap, sizeof (literal_t));
  274. (*literal)->value = value;
  275. (*literal)->offset = gen->literal_pool_size;
  276. gen->literal_pool_size += sizeof(U32);
  277. return (*literal)->offset;
  278. }
  279. cg_codegen_t * cg_codegen_create(cg_heap_t * heap, cg_runtime_info_t * runtime,
  280. cg_processor_info_t * processor)
  281. {
  282. size_t regno;
  283. cg_codegen_t * gen =
  284. (cg_codegen_t *) cg_heap_allocate(heap, sizeof(cg_codegen_t));
  285. memset(gen, 0, sizeof *gen);
  286. gen->runtime = runtime;
  287. gen->processor = processor;
  288. gen->heap = heap;
  289. gen->labels = (cg_label_t *) 0;
  290. gen->cseg = cg_segment_create("CSEG");
  291. for (regno = 0; regno != PHYSICAL_REGISTERS; ++regno)
  292. {
  293. gen->registers[regno].regno = (ARMReg) (ARMREG_R0 + regno);
  294. }
  295. gen->flags.regno = ARMREG_CPSR;
  296. return gen;
  297. }
  298. void cg_codegen_destroy(cg_codegen_t * gen)
  299. {
  300. cg_segment_destroy(gen->cseg);
  301. }
  302. /****************************************************************************/
  303. /* Processing of individual instructions */
  304. /****************************************************************************/
  305. static cg_physical_reg_t * allocate_reg(cg_codegen_t * gen, cg_virtual_reg_t * reg,
  306. U32 mask);
  307. static void deallocate_reg(cg_codegen_t * gen, cg_physical_reg_t * physical_reg);
  308. static void assign_reg(cg_codegen_t * gen,
  309. cg_physical_reg_t * physical_reg,
  310. cg_virtual_reg_t * reg);
  311. static void make_global(cg_codegen_t * gen, cg_physical_reg_t * reg);
  312. static cg_physical_reg_t * load_reg(cg_codegen_t * gen, cg_virtual_reg_t * reg,
  313. U32 mask);
  314. static ARMShiftType arm_shift_type(cg_shift_op_t shift_op)
  315. {
  316. switch (shift_op)
  317. {
  318. default:
  319. assert(0);
  320. case cg_shift_lsl:
  321. return ARMSHIFT_LSL;
  322. case cg_shift_lsr:
  323. return ARMSHIFT_LSR;
  324. case cg_shift_asr:
  325. return ARMSHIFT_ASR;
  326. case cg_shift_ror:
  327. return ARMSHIFT_ROR;
  328. }
  329. }
  330. static void branch_cond(cg_codegen_t * gen, cg_label_t * target, ARMCond cond)
  331. {
  332. /* insert a conditional branch to the specified target label */
  333. cg_codegen_reference(gen, target, cg_reference_branch24);
  334. /* compensate for PC pointing 2 instruction words ahead */
  335. ARM_B_COND(gen->cseg, cond, -2 & 0xFFFFFF);
  336. }
  337. static void branch(cg_codegen_t * gen, cg_label_t * target)
  338. {
  339. branch_cond(gen, target, ARMCOND_AL);
  340. }
  341. static void save_flags(cg_codegen_t * gen, cg_physical_reg_t * physical_reg)
  342. {
  343. ARM_MRS_CPSR(gen->cseg, physical_reg->regno);
  344. }
  345. static void restore_flags(cg_codegen_t * gen, cg_physical_reg_t * reg)
  346. {
  347. ARM_MSR_REG(gen->cseg, ARM_PSR_F, reg->regno, ARM_CPSR);
  348. }
  349. static void call_store_additional_args(cg_codegen_t * gen, cg_virtual_reg_list_t * args, cg_inst_t * inst)
  350. {
  351. /* In case we have more than 4 arguments: store all remaining args onto the stack */
  352. ARMReg regno;
  353. for (regno = ARMREG_A1; regno <= ARMREG_A4 && args != (cg_virtual_reg_list_t *) 0;
  354. ++regno, args = args->next)
  355. ; /* skip register arguments */
  356. if (args != (cg_virtual_reg_list_t *) 0)
  357. {
  358. size_t argument_base_offset = 0;
  359. do
  360. {
  361. cg_virtual_reg_t * reg = args->reg;
  362. cg_physical_reg_t * physical_reg;
  363. cg_inst_list_t ** plist = &gen->use_chains[reg->reg_no];
  364. while (*plist != (cg_inst_list_t *) 0 &&
  365. (*plist)->inst != inst)
  366. {
  367. plist = &(*plist)->next;
  368. }
  369. if (*plist != 0)
  370. {
  371. *plist = (*plist)->next;
  372. }
  373. physical_reg = load_reg(gen, reg, 0);
  374. /* save the register into the parameter area */
  375. ARM_STR_IMM(gen->cseg, physical_reg->regno, ARMREG_FP, argument_base_offset);
  376. if (gen->use_chains[reg->reg_no] == (cg_inst_list_t *) 0)
  377. {
  378. deallocate_reg(gen, physical_reg);
  379. }
  380. args = args->next;
  381. argument_base_offset += sizeof(U32);
  382. }
  383. while (args != (cg_virtual_reg_list_t *) 0);
  384. }
  385. }
  386. static void load_register_arg(cg_codegen_t * gen, cg_virtual_reg_t * reg, ARMReg regno, cg_inst_t * inst)
  387. {
  388. U32 mask = 1u << regno;
  389. /* force argument into the specified register */
  390. cg_physical_reg_t * physical_reg;
  391. cg_inst_list_t ** plist = &gen->use_chains[reg->reg_no];
  392. while (*plist != (cg_inst_list_t *) 0 &&
  393. (*plist)->inst != inst)
  394. {
  395. plist = &(*plist)->next;
  396. }
  397. if (*plist != 0)
  398. {
  399. *plist = (*plist)->next;
  400. }
  401. physical_reg = load_reg(gen, reg, mask);
  402. assert(physical_reg->virtual_reg == reg);
  403. }
  404. static void kill_argument_registers(cg_codegen_t * gen)
  405. {
  406. ARMReg regno;
  407. for (regno = ARMREG_A1; regno <= ARMREG_A4; ++regno)
  408. {
  409. cg_physical_reg_t * physical_reg = gen->registers + regno;
  410. cg_virtual_reg_t * reg = physical_reg->virtual_reg;
  411. if (reg != NULL)
  412. {
  413. if (reg->physical_reg == physical_reg)
  414. {
  415. deallocate_reg(gen, physical_reg);
  416. }
  417. else
  418. {
  419. /* register is a duplicate of another register, just free it up */
  420. reg_list_remove(&gen->used_regs, physical_reg);
  421. reg_list_add(&gen->free_regs, physical_reg);
  422. physical_reg->virtual_reg = 0;
  423. }
  424. }
  425. }
  426. }
  427. static void kill_flags(cg_codegen_t * gen)
  428. {
  429. if (gen->flags.virtual_reg != NULL &&
  430. gen->flags.virtual_reg->physical_reg == &gen->flags)
  431. {
  432. cg_virtual_reg_t * reg = gen->flags.virtual_reg;
  433. int used = CG_BITSET_TEST(gen->current_block->live_out, reg->reg_no) ||
  434. gen->use_chains[reg->reg_no];
  435. if (used)
  436. {
  437. cg_physical_reg_t * physical_reg = allocate_reg(gen, reg, 0);
  438. assign_reg(gen, physical_reg, reg);
  439. save_flags(gen, physical_reg);
  440. physical_reg->dirty = physical_reg->defined = 1;
  441. }
  442. }
  443. }
  444. static void call_load_register_args(cg_codegen_t * gen, cg_virtual_reg_list_t * begin_args, cg_inst_t * inst)
  445. {
  446. ARMReg regno;
  447. cg_virtual_reg_list_t * args;
  448. for (regno = ARMREG_A1, args = begin_args; regno <= ARMREG_A4 && args != (cg_virtual_reg_list_t *) 0;
  449. ++regno, args = args->next)
  450. {
  451. load_register_arg(gen, args->reg, regno, inst);
  452. }
  453. kill_flags(gen);
  454. kill_argument_registers(gen);
  455. }
  456. static void call_runtime(cg_codegen_t * gen, void * target)
  457. {
  458. /* create the necessary code sequence to call into a procedure that is */
  459. /* part of the runtime library */
  460. ARM_MOV_REG_REG(gen->cseg, ARMREG_LR, ARMREG_PC);
  461. cg_codegen_reference(gen, gen->literal_base, cg_reference_offset12);
  462. ARM_LDR_IMM(gen->cseg, ARMREG_PC, ARMREG_PC,
  463. (cg_codegen_emit_literal(gen, (U32) target, 0) - 8) & 0xfff);
  464. }
  465. static void call(cg_codegen_t * gen, cg_label_t * target,
  466. cg_virtual_reg_list_t * args, cg_inst_t * inst)
  467. {
  468. /* create the necessary code sequence to call into a procedure */
  469. call_store_additional_args(gen, args, inst);
  470. call_load_register_args(gen, args, inst);
  471. cg_codegen_reference(gen, target, cg_reference_branch24);
  472. ARM_BL(gen->cseg, -2);
  473. }
  474. static void emit_unary_negate(cg_codegen_t * gen, cg_inst_unary_t * inst,
  475. int update_flags)
  476. {
  477. switch (inst->base.kind)
  478. {
  479. case cg_inst_unary:
  480. if (update_flags)
  481. ARM_RSBS_REG_IMM(gen->cseg,
  482. inst->dest_value->physical_reg->regno,
  483. inst->operand.source->physical_reg->regno,
  484. 0, 0);
  485. else
  486. ARM_RSB_REG_IMM(gen->cseg,
  487. inst->dest_value->physical_reg->regno,
  488. inst->operand.source->physical_reg->regno,
  489. 0, 0);
  490. break;
  491. default:
  492. assert(0);
  493. }
  494. }
  495. static void emit_unary_complement(cg_codegen_t * gen, cg_inst_unary_t * inst,
  496. int update_flags)
  497. {
  498. switch (inst->base.kind)
  499. {
  500. case cg_inst_unary:
  501. if (update_flags)
  502. ARM_MVNS_REG_REG(gen->cseg,
  503. inst->dest_value->physical_reg->regno,
  504. inst->operand.source->physical_reg->regno);
  505. else
  506. ARM_MVN_REG_REG(gen->cseg,
  507. inst->dest_value->physical_reg->regno,
  508. inst->operand.source->physical_reg->regno);
  509. break;
  510. case cg_inst_arm_unary_immed:
  511. assert(inst->operand.immed >= 0 && inst->operand.immed <= 0xff);
  512. if (update_flags)
  513. ARM_MVNS_REG_IMM(gen->cseg,
  514. inst->dest_value->physical_reg->regno,
  515. inst->operand.immed, 0);
  516. else
  517. ARM_MVN_REG_IMM(gen->cseg,
  518. inst->dest_value->physical_reg->regno,
  519. inst->operand.immed, 0);
  520. break;
  521. case cg_inst_arm_unary_shift_reg:
  522. if (update_flags)
  523. ARM_MVNS_REG_REGSHIFT(gen->cseg,
  524. inst->dest_value->physical_reg->regno,
  525. inst->operand.shift_reg.source->physical_reg->regno,
  526. arm_shift_type(inst->operand.shift_reg.op),
  527. inst->operand.shift_reg.shift->physical_reg->regno);
  528. else
  529. ARM_MVN_REG_REGSHIFT(gen->cseg,
  530. inst->dest_value->physical_reg->regno,
  531. inst->operand.shift_reg.source->physical_reg->regno,
  532. arm_shift_type(inst->operand.shift_reg.op),
  533. inst->operand.shift_reg.shift->physical_reg->regno);
  534. break;
  535. case cg_inst_arm_unary_shift_immed:
  536. if (update_flags)
  537. ARM_MVNS_REG_IMMSHIFT(gen->cseg,
  538. inst->dest_value->physical_reg->regno,
  539. inst->operand.shift_immed.source->physical_reg->regno,
  540. arm_shift_type(inst->operand.shift_immed.op),
  541. inst->operand.shift_immed.shift);
  542. else
  543. ARM_MVN_REG_IMMSHIFT(gen->cseg,
  544. inst->dest_value->physical_reg->regno,
  545. inst->operand.shift_immed.source->physical_reg->regno,
  546. arm_shift_type(inst->operand.shift_immed.op),
  547. inst->operand.shift_immed.shift);
  548. break;
  549. default:
  550. assert(0);
  551. }
  552. }
  553. static void emit_unary_trunc(cg_codegen_t * gen, cg_inst_unary_t * inst,
  554. int update_flags)
  555. {
  556. assert(inst->base.kind == cg_inst_unary);
  557. if (update_flags)
  558. ARM_MOVS_REG_IMMSHIFT(gen->cseg,
  559. inst->dest_value->physical_reg->regno,
  560. inst->operand.source->physical_reg->regno,
  561. ARMSHIFT_ASR, 16);
  562. else
  563. ARM_MOV_REG_IMMSHIFT(gen->cseg,
  564. inst->dest_value->physical_reg->regno,
  565. inst->operand.source->physical_reg->regno,
  566. ARMSHIFT_ASR, 16);
  567. }
  568. static void emit_unary_round(cg_codegen_t * gen, cg_inst_unary_t * inst,
  569. int update_flags)
  570. {
  571. assert(inst->base.kind == cg_inst_unary);
  572. ARM_ADD_REG_IMM(gen->cseg,
  573. inst->dest_value->physical_reg->regno,
  574. inst->operand.source->physical_reg->regno,
  575. 0x80, 24);
  576. if (update_flags)
  577. ARM_MOVS_REG_IMMSHIFT(gen->cseg,
  578. inst->dest_value->physical_reg->regno,
  579. inst->dest_value->physical_reg->regno,
  580. ARMSHIFT_ASR, 16);
  581. else
  582. ARM_MOV_REG_IMMSHIFT(gen->cseg,
  583. inst->dest_value->physical_reg->regno,
  584. inst->dest_value->physical_reg->regno,
  585. ARMSHIFT_ASR, 16);
  586. }
  587. static void emit_unary_fcnv(cg_codegen_t * gen, cg_inst_unary_t * inst,
  588. int update_flags)
  589. {
  590. assert(inst->base.kind == cg_inst_unary);
  591. if (update_flags)
  592. ARM_MOVS_REG_IMMSHIFT(gen->cseg,
  593. inst->dest_value->physical_reg->regno,
  594. inst->operand.source->physical_reg->regno,
  595. ARMSHIFT_LSL, 16);
  596. else
  597. ARM_MOV_REG_IMMSHIFT(gen->cseg,
  598. inst->dest_value->physical_reg->regno,
  599. inst->operand.source->physical_reg->regno,
  600. ARMSHIFT_LSL, 16);
  601. }
  602. static void emit_unary_abs(cg_codegen_t * gen, cg_inst_unary_t * inst, int update_flags)
  603. {
  604. assert(!update_flags);
  605. assert(inst->base.kind == cg_inst_unary);
  606. ARM_CMP_REG_IMM8(gen->cseg,
  607. inst->operand.source->physical_reg->regno,
  608. 0);
  609. ARM_MOV_REG_REG_COND(gen->cseg,
  610. inst->dest_value->physical_reg->regno,
  611. inst->operand.source->physical_reg->regno,
  612. ARMCOND_GE);
  613. ARM_MVN_REG_REG_COND(gen->cseg,
  614. inst->dest_value->physical_reg->regno,
  615. inst->operand.source->physical_reg->regno,
  616. ARMCOND_LT);
  617. }
  618. static void emit_unary_log2(cg_codegen_t * gen, cg_inst_unary_t * inst, int update_flags)
  619. {
  620. assert(!update_flags);
  621. assert(inst->base.kind == cg_inst_unary);
  622. if (gen->processor->useV5) {
  623. ARM_CLZ(gen->cseg,
  624. inst->dest_value->physical_reg->regno,
  625. inst->operand.source->physical_reg->regno);
  626. ARM_RSBS_REG_IMM8(gen->cseg,
  627. inst->dest_value->physical_reg->regno,
  628. inst->dest_value->physical_reg->regno,
  629. 31);
  630. ARM_MOV_REG_IMM8_COND(gen->cseg,
  631. inst->dest_value->physical_reg->regno,
  632. 0,
  633. ARMCOND_MI);
  634. } else {
  635. // allocate a temporary register
  636. cg_virtual_reg_t temp_reg0, temp_reg1;
  637. cg_physical_reg_t * temp_physical_reg0, *temp_physical_reg1;
  638. U32 mask;
  639. memset(&temp_reg0, 0, sizeof temp_reg0);
  640. memset(&temp_reg1, 0, sizeof temp_reg1);
  641. /* may need to create a mask based on the registers allocated for */
  642. /* the other operands */
  643. mask = ~((1u << inst->dest_value->physical_reg->regno) |
  644. (1u << inst->operand.source->physical_reg->regno));
  645. temp_physical_reg0 = allocate_reg(gen, &temp_reg0, mask);
  646. assign_reg(gen, temp_physical_reg0, &temp_reg0);
  647. mask &= ~(1u << temp_physical_reg0->regno);
  648. temp_physical_reg1 = allocate_reg(gen, &temp_reg1, mask);
  649. assign_reg(gen, temp_physical_reg1, &temp_reg1);
  650. //exp = 0;
  651. ARM_MOV_REG_IMM8(gen->cseg,
  652. inst->dest_value->physical_reg->regno,
  653. 0);
  654. ARM_MOV_REG_REG(gen->cseg,
  655. temp_physical_reg0->regno,
  656. inst->operand.source->physical_reg->regno);
  657. //if (f & 0xff00) { exp += 8; f >>= 8; }
  658. ARM_ANDS_REG_IMM(gen->cseg,
  659. temp_physical_reg1->regno,
  660. temp_physical_reg0->regno,
  661. 0xff,
  662. calc_arm_mov_const_shift(0xff00));
  663. ARM_MOV_REG_IMM8_COND(gen->cseg,
  664. inst->dest_value->physical_reg->regno,
  665. 8, ARMCOND_NE);
  666. ARM_MOV_REG_IMMSHIFT_COND(gen->cseg,
  667. temp_physical_reg0->regno,
  668. temp_physical_reg0->regno,
  669. ARMSHIFT_ASR, 8, ARMCOND_NE);
  670. //if (f & 0xf0) { exp += 4; f >>= 4; }
  671. ARM_ANDS_REG_IMM8(gen->cseg,
  672. temp_physical_reg1->regno,
  673. temp_physical_reg0->regno,
  674. 0xf0);
  675. ARM_ADD_REG_IMM8_COND(gen->cseg,
  676. inst->dest_value->physical_reg->regno,
  677. inst->dest_value->physical_reg->regno,
  678. 4, ARMCOND_NE);
  679. ARM_MOV_REG_IMMSHIFT_COND(gen->cseg,
  680. temp_physical_reg0->regno,
  681. temp_physical_reg0->regno,
  682. ARMSHIFT_ASR, 4, ARMCOND_NE);
  683. //if (f & 0xc) { exp += 2; f >>= 2; }
  684. ARM_ANDS_REG_IMM8(gen->cseg,
  685. temp_physical_reg1->regno,
  686. temp_physical_reg0->regno,
  687. 0xc);
  688. ARM_ADD_REG_IMM8_COND(gen->cseg,
  689. inst->dest_value->physical_reg->regno,
  690. inst->dest_value->physical_reg->regno,
  691. 2, ARMCOND_NE);
  692. ARM_MOV_REG_IMMSHIFT_COND(gen->cseg,
  693. temp_physical_reg0->regno,
  694. temp_physical_reg0->regno,
  695. ARMSHIFT_ASR, 2, ARMCOND_NE);
  696. //if (f & 0x2) { exp += 1; }
  697. ARM_ANDS_REG_IMM8(gen->cseg,
  698. temp_physical_reg1->regno,
  699. temp_physical_reg0->regno,
  700. 0x2);
  701. ARM_ADD_REG_IMM8_COND(gen->cseg,
  702. inst->dest_value->physical_reg->regno,
  703. inst->dest_value->physical_reg->regno,
  704. 1, ARMCOND_NE);
  705. // release the temporary register
  706. deallocate_reg(gen, temp_physical_reg0);
  707. deallocate_reg(gen, temp_physical_reg1);
  708. }
  709. }
  710. static void emit_unary(cg_codegen_t * gen, cg_inst_unary_t * inst,
  711. int update_flags)
  712. {
  713. // distinguish operations that map directly to ARM instructions
  714. // operations that require sequence of instructions
  715. // operations that map into a function call
  716. switch (inst->base.opcode)
  717. {
  718. /* regular unary operation */
  719. case cg_op_neg:
  720. case cg_op_fneg:
  721. emit_unary_negate(gen, inst, update_flags);
  722. break;
  723. case cg_op_not:
  724. emit_unary_complement(gen, inst, update_flags);
  725. break;
  726. /* sequences */
  727. case cg_op_trunc:
  728. emit_unary_trunc(gen, inst, update_flags);
  729. break;
  730. case cg_op_round:
  731. emit_unary_round(gen, inst, update_flags);
  732. break;
  733. case cg_op_fcnv:
  734. emit_unary_fcnv(gen, inst, update_flags);
  735. break;
  736. case cg_op_abs:
  737. emit_unary_abs(gen, inst, update_flags);
  738. break;
  739. case cg_op_log2:
  740. emit_unary_log2(gen, inst, update_flags);
  741. break;
  742. default:
  743. assert(0);
  744. }
  745. }
  746. static void emit_binary_shifter(cg_codegen_t * gen, cg_inst_binary_t * inst,
  747. int update_flags)
  748. {
  749. ARMShiftType shift_type;
  750. switch (inst->base.opcode)
  751. {
  752. default:
  753. assert(0);
  754. case cg_op_lsl:
  755. shift_type = ARMSHIFT_LSL;
  756. break;
  757. case cg_op_lsr:
  758. shift_type = ARMSHIFT_LSR;
  759. break;
  760. case cg_op_asr:
  761. shift_type = ARMSHIFT_ASR;
  762. break;
  763. }
  764. switch (inst->base.kind)
  765. {
  766. case cg_inst_binary:
  767. if (update_flags)
  768. ARM_MOVS_REG_REGSHIFT(gen->cseg,
  769. inst->dest_value->physical_reg->regno,
  770. inst->source->physical_reg->regno,
  771. shift_type,
  772. inst->operand.source->physical_reg->regno);
  773. else
  774. ARM_MOV_REG_REGSHIFT(gen->cseg,
  775. inst->dest_value->physical_reg->regno,
  776. inst->source->physical_reg->regno,
  777. shift_type,
  778. inst->operand.source->physical_reg->regno);
  779. break;
  780. case cg_inst_arm_binary_immed:
  781. if (update_flags)
  782. ARM_MOVS_REG_IMMSHIFT(gen->cseg,
  783. inst->dest_value->physical_reg->regno,
  784. inst->source->physical_reg->regno,
  785. shift_type,
  786. inst->operand.immed);
  787. else
  788. ARM_MOV_REG_IMMSHIFT(gen->cseg,
  789. inst->dest_value->physical_reg->regno,
  790. inst->source->physical_reg->regno,
  791. shift_type,
  792. inst->operand.immed);
  793. break;
  794. default:
  795. assert(0);
  796. }
  797. }
  798. static void emit_binary_regular(cg_codegen_t * gen, cg_inst_binary_t * inst,
  799. ARMOpcode opcode, int update_flags)
  800. {
  801. int shift;
  802. switch (inst->base.kind)
  803. {
  804. case cg_inst_binary:
  805. if (update_flags)
  806. ARM_DPIOP_S_REG_REG_COND(gen->cseg,
  807. opcode,
  808. inst->dest_value->physical_reg->regno,
  809. inst->source->physical_reg->regno,
  810. inst->operand.source->physical_reg->regno,
  811. ARMCOND_AL);
  812. else
  813. ARM_DPIOP_REG_REG_COND(gen->cseg,
  814. opcode,
  815. inst->dest_value->physical_reg->regno,
  816. inst->source->physical_reg->regno,
  817. inst->operand.source->physical_reg->regno,
  818. ARMCOND_AL);
  819. break;
  820. case cg_inst_arm_binary_immed:
  821. shift = calc_arm_mov_const_shift(inst->operand.immed);
  822. assert((shift & 0x80000001) != 1 && shift >= 0);
  823. if (update_flags)
  824. ARM_DPIOP_S_REG_IMM8ROT_COND(gen->cseg,
  825. opcode,
  826. inst->dest_value->physical_reg->regno,
  827. inst->source->physical_reg->regno,
  828. inst->operand.immed >> ((32 - shift) & 31), shift,
  829. ARMCOND_AL);
  830. else
  831. ARM_DPIOP_REG_IMM8ROT_COND(gen->cseg,
  832. opcode,
  833. inst->dest_value->physical_reg->regno,
  834. inst->source->physical_reg->regno,
  835. inst->operand.immed >> ((32 - shift) & 31), shift,
  836. ARMCOND_AL);
  837. break;
  838. case cg_inst_arm_binary_shift_reg:
  839. if (update_flags)
  840. ARM_DPIOP_S_REG_REGSHIFT_COND(gen->cseg,
  841. opcode,
  842. inst->dest_value->physical_reg->regno,
  843. inst->source->physical_reg->regno,
  844. inst->operand.shift_reg.source->physical_reg->regno,
  845. arm_shift_type(inst->operand.shift_reg.op),
  846. inst->operand.shift_reg.shift->physical_reg->regno,
  847. ARMCOND_AL);
  848. else
  849. ARM_DPIOP_REG_REGSHIFT_COND(gen->cseg,
  850. opcode,
  851. inst->dest_value->physical_reg->regno,
  852. inst->source->physical_reg->regno,
  853. inst->operand.shift_reg.source->physical_reg->regno,
  854. arm_shift_type(inst->operand.shift_reg.op),
  855. inst->operand.shift_reg.shift->physical_reg->regno,
  856. ARMCOND_AL);
  857. break;
  858. case cg_inst_arm_binary_shift_immed:
  859. if (update_flags)
  860. ARM_DPIOP_S_REG_IMMSHIFT_COND(gen->cseg,
  861. opcode,
  862. inst->dest_value->physical_reg->regno,
  863. inst->source->physical_reg->regno,
  864. inst->operand.shift_immed.source->physical_reg->regno,
  865. arm_shift_type(inst->operand.shift_immed.op),
  866. inst->operand.shift_immed.shift,
  867. ARMCOND_AL);
  868. else
  869. ARM_DPIOP_REG_IMMSHIFT_COND(gen->cseg,
  870. opcode,
  871. inst->dest_value->physical_reg->regno,
  872. inst->source->physical_reg->regno,
  873. inst->operand.shift_immed.source->physical_reg->regno,
  874. arm_shift_type(inst->operand.shift_immed.op),
  875. inst->operand.shift_immed.shift,
  876. ARMCOND_AL);
  877. break;
  878. default:
  879. assert(0);
  880. }
  881. }
  882. static void emit_binary_multiply_int(cg_codegen_t * gen, cg_inst_binary_t * inst,
  883. int update_flags)
  884. {
  885. assert(inst->base.kind == cg_inst_binary);
  886. if (update_flags)
  887. ARM_MULS(gen->cseg,
  888. inst->dest_value->physical_reg->regno,
  889. inst->source->physical_reg->regno,
  890. inst->operand.source->physical_reg->regno);
  891. else
  892. ARM_MUL(gen->cseg,
  893. inst->dest_value->physical_reg->regno,
  894. inst->source->physical_reg->regno,
  895. inst->operand.source->physical_reg->regno);
  896. }
  897. static void emit_binary_multiply_fixed(cg_codegen_t * gen, cg_inst_binary_t * inst,
  898. int update_flags)
  899. {
  900. // alloacte a temporary register
  901. cg_virtual_reg_t temp_reg;
  902. cg_physical_reg_t * temp_physical_reg;
  903. U32 mask;
  904. assert(inst->base.kind == cg_inst_binary);
  905. memset(&temp_reg, 0, sizeof temp_reg);
  906. /* may need to create a mask based on the registers allocated for */
  907. /* the other operands */
  908. mask = ~((1u << inst->dest_value->physical_reg->regno) |
  909. (1u << inst->source->physical_reg->regno) |
  910. (1u << inst->operand.source->physical_reg->regno));
  911. temp_physical_reg = allocate_reg(gen, &temp_reg, mask);
  912. assign_reg(gen, temp_physical_reg, &temp_reg);
  913. ARM_SMULL(gen->cseg,
  914. inst->dest_value->physical_reg->regno,
  915. temp_physical_reg->regno,
  916. inst->source->physical_reg->regno,
  917. inst->operand.source->physical_reg->regno);
  918. ARM_MOV_REG_IMMSHIFT(gen->cseg,
  919. inst->dest_value->physical_reg->regno,
  920. inst->dest_value->physical_reg->regno,
  921. ARMSHIFT_LSR,
  922. 16);
  923. if (update_flags)
  924. ARM_ORRS_REG_IMMSHIFT(gen->cseg,
  925. inst->dest_value->physical_reg->regno,
  926. inst->dest_value->physical_reg->regno,
  927. temp_physical_reg->regno,
  928. ARMSHIFT_LSL,
  929. 16);
  930. else
  931. ARM_ORR_REG_IMMSHIFT(gen->cseg,
  932. inst->dest_value->physical_reg->regno,
  933. inst->dest_value->physical_reg->regno,
  934. temp_physical_reg->regno,
  935. ARMSHIFT_LSL,
  936. 16);
  937. // release the temporary register
  938. deallocate_reg(gen, temp_physical_reg);
  939. }
  940. static void emit_binary_minmax(cg_codegen_t * gen, cg_inst_binary_t * inst, int update_flags)
  941. {
  942. ARMCond condition;
  943. ARMCond neg_condition;
  944. int shift;
  945. assert(!update_flags);
  946. emit_binary_regular(gen, inst, ARMOP_CMP, 1);
  947. switch (inst->base.opcode) {
  948. case cg_op_min:
  949. condition = ARMCOND_LE;
  950. neg_condition = ARMCOND_GT;
  951. break;
  952. case cg_op_max:
  953. condition = ARMCOND_GE;
  954. neg_condition = ARMCOND_LT;
  955. break;
  956. default:
  957. assert(0);
  958. break;
  959. }
  960. if (inst->dest_value->physical_reg->regno != inst->source->physical_reg->regno) {
  961. ARM_MOV_REG_REG_COND(gen->cseg,
  962. inst->dest_value->physical_reg->regno,
  963. inst->source->physical_reg->regno,
  964. condition);
  965. }
  966. /*ARM_MOV_REG_REG_COND(gen->cseg,
  967. inst->dest_value->physical_reg->regno,
  968. inst->operand.source->physical_reg->regno,
  969. neg_condition);*/
  970. switch (inst->base.kind)
  971. {
  972. case cg_inst_binary:
  973. ARM_DPIOP_REG_REG_COND(gen->cseg,
  974. ARMOP_MOV,
  975. inst->dest_value->physical_reg->regno,
  976. 0,
  977. inst->operand.source->physical_reg->regno,
  978. neg_condition);
  979. break;
  980. case cg_inst_arm_binary_immed:
  981. shift = calc_arm_mov_const_shift(inst->operand.immed);
  982. assert((shift & 0x80000001) != 1 && shift >= 0);
  983. ARM_DPIOP_REG_IMM8ROT_COND(gen->cseg,
  984. ARMOP_MOV,
  985. inst->dest_value->physical_reg->regno,
  986. 0,
  987. inst->operand.immed >> ((32 - shift) & 31), shift,
  988. neg_condition);
  989. break;
  990. case cg_inst_arm_binary_shift_reg:
  991. ARM_DPIOP_REG_REGSHIFT_COND(gen->cseg,
  992. ARMOP_MOV,
  993. inst->dest_value->physical_reg->regno,
  994. 0,
  995. inst->operand.shift_reg.source->physical_reg->regno,
  996. arm_shift_type(inst->operand.shift_reg.op),
  997. inst->operand.shift_reg.shift->physical_reg->regno,
  998. neg_condition);
  999. break;
  1000. case cg_inst_arm_binary_shift_immed:
  1001. ARM_DPIOP_REG_IMMSHIFT_COND(gen->cseg,
  1002. ARMOP_MOV,
  1003. inst->dest_value->physical_reg->regno,
  1004. 0,
  1005. inst->operand.shift_immed.source->physical_reg->regno,
  1006. arm_shift_type(inst->operand.shift_immed.op),
  1007. inst->operand.shift_immed.shift,
  1008. neg_condition);
  1009. break;
  1010. default:
  1011. assert(0);
  1012. }
  1013. }
  1014. static void emit_binary(cg_codegen_t * gen, cg_inst_binary_t * inst, int update_flags)
  1015. {
  1016. // distinguish operations that map directly to ARM instructions
  1017. // shifter-type instructions (MOV plus shifter operand)
  1018. // operations that require sequence of instructions
  1019. // operations that map into a function call
  1020. switch (inst->base.opcode)
  1021. {
  1022. /* shifter type */
  1023. case cg_op_asr:
  1024. case cg_op_lsl:
  1025. case cg_op_lsr:
  1026. emit_binary_shifter(gen, inst, update_flags);
  1027. break;
  1028. /* regular binary operation */
  1029. case cg_op_add:
  1030. case cg_op_fadd:
  1031. emit_binary_regular(gen, inst, ARMOP_ADD, update_flags);
  1032. break;
  1033. case cg_op_sub:
  1034. case cg_op_fsub:
  1035. emit_binary_regular(gen, inst, ARMOP_SUB, update_flags);
  1036. break;
  1037. case cg_op_and:
  1038. emit_binary_regular(gen, inst, ARMOP_AND, update_flags);
  1039. break;
  1040. case cg_op_or:
  1041. emit_binary_regular(gen, inst, ARMOP_ORR, update_flags);
  1042. break;
  1043. case cg_op_xor:
  1044. emit_binary_regular(gen, inst, ARMOP_EOR, update_flags);
  1045. break;
  1046. /* multiplication */
  1047. case cg_op_mul:
  1048. emit_binary_multiply_int(gen, inst, update_flags);
  1049. break;
  1050. case cg_op_fmul:
  1051. emit_binary_multiply_fixed(gen, inst, update_flags);
  1052. break;
  1053. /* min and max */
  1054. case cg_op_min:
  1055. case cg_op_max:
  1056. emit_binary_minmax(gen, inst, update_flags);
  1057. break;
  1058. default:
  1059. assert(0);
  1060. }
  1061. }
  1062. static void emit_compare(cg_codegen_t * gen, cg_inst_compare_t * inst)
  1063. {
  1064. ARMShiftType shift_type;
  1065. int shift;
  1066. assert(inst->base.opcode == cg_op_cmp ||
  1067. inst->base.opcode == cg_op_fcmp);
  1068. switch (inst->base.kind)
  1069. {
  1070. case cg_inst_compare:
  1071. ARM_CMP_REG_REG(gen->cseg,
  1072. inst->source->physical_reg->regno,
  1073. inst->operand.source->physical_reg->regno);
  1074. break;
  1075. case cg_inst_arm_compare_immed:
  1076. shift = calc_arm_mov_const_shift(inst->operand.immed);
  1077. if ((shift & 0x80000001) != 1) {
  1078. if (shift >= 0) {
  1079. ARM_CMP_REG_IMM(gen->cseg, inst->source->physical_reg->regno, inst->operand.immed >> ((32 - shift) & 31), shift);
  1080. } else {
  1081. ARM_CMN_REG_IMM(gen->cseg, inst->source->physical_reg->regno, (inst->operand.immed ^ (~0)) >> ((32 + 2 + shift) & 31), (-shift - 2));
  1082. }
  1083. } else {
  1084. assert(0);
  1085. }
  1086. break;
  1087. case cg_inst_arm_compare_shift_reg:
  1088. shift_type = arm_shift_type(inst->operand.shift_reg.op);
  1089. ARM_CMP_REG_REGSHIFT(gen->cseg,
  1090. inst->source->physical_reg->regno,
  1091. inst->operand.shift_reg.source->physical_reg->regno,
  1092. shift_type,
  1093. inst->operand.shift_reg.shift->physical_reg->regno);
  1094. break;
  1095. case cg_inst_arm_compare_shift_immed:
  1096. shift_type = arm_shift_type(inst->operand.shift_immed.op);
  1097. ARM_CMP_REG_IMMSHIFT(gen->cseg,
  1098. inst->source->physical_reg->regno,
  1099. inst->operand.shift_immed.source->physical_reg->regno,
  1100. shift_type,
  1101. inst->operand.shift_immed.shift);
  1102. break;
  1103. default:
  1104. assert(0);
  1105. }
  1106. }
  1107. static void emit_load(cg_codegen_t * gen, cg_inst_load_t * inst)
  1108. {
  1109. switch (inst->base.opcode)
  1110. {
  1111. case cg_op_ldb:
  1112. switch (inst->base.kind)
  1113. {
  1114. case cg_inst_load:
  1115. ARM_LDRB_IMM(gen->cseg, inst->dest->physical_reg->regno,
  1116. inst->mem.base->physical_reg->regno, 0);
  1117. break;
  1118. case cg_inst_arm_load_immed_offset:
  1119. ARM_LDRB_IMM(gen->cseg, inst->dest->physical_reg->regno,
  1120. inst->mem.immed_offset.base->physical_reg->regno,
  1121. inst->mem.immed_offset.offset);
  1122. break;
  1123. case cg_inst_arm_load_reg_offset:
  1124. ARM_LDRB_REG_REG(gen->cseg, inst->dest->physical_reg->regno,
  1125. inst->mem.reg_offset.base->physical_reg->regno,
  1126. inst->mem.reg_offset.offset->physical_reg->regno);
  1127. break;
  1128. default:
  1129. assert(0);
  1130. }
  1131. break;
  1132. case cg_op_ldh:
  1133. switch (inst->base.kind)
  1134. {
  1135. case cg_inst_load:
  1136. ARM_LDRH_IMM(gen->cseg, inst->dest->physical_reg->regno,
  1137. inst->mem.base->physical_reg->regno, 0);
  1138. break;
  1139. case cg_inst_arm_load_immed_offset:
  1140. ARM_LDRH_IMM(gen->cseg, inst->dest->physical_reg->regno,
  1141. inst->mem.immed_offset.base->physical_reg->regno,
  1142. inst->mem.immed_offset.offset);
  1143. break;
  1144. case cg_inst_arm_load_reg_offset:
  1145. ARM_LDRH_REG_REG(gen->cseg, inst->dest->physical_reg->regno,
  1146. inst->mem.reg_offset.base->physical_reg->regno,
  1147. inst->mem.reg_offset.offset->physical_reg->regno);
  1148. break;
  1149. default:
  1150. assert(0);
  1151. }
  1152. break;
  1153. case cg_op_ldw:
  1154. switch (inst->base.kind)
  1155. {
  1156. case cg_inst_load:
  1157. ARM_LDR_IMM(gen->cseg, inst->dest->physical_reg->regno,
  1158. inst->mem.base->physical_reg->regno, 0);
  1159. break;
  1160. case cg_inst_arm_load_immed_offset:
  1161. ARM_LDR_IMM(gen->cseg, inst->dest->physical_reg->regno,
  1162. inst->mem.immed_offset.base->physical_reg->regno,
  1163. inst->mem.immed_offset.offset);
  1164. break;
  1165. case cg_inst_arm_load_reg_offset:
  1166. ARM_LDR_REG_REG(gen->cseg, inst->dest->physical_reg->regno,
  1167. inst->mem.reg_offset.base->physical_reg->regno,
  1168. inst->mem.reg_offset.offset->physical_reg->regno);
  1169. break;
  1170. default:
  1171. assert(0);
  1172. }
  1173. break;
  1174. default:
  1175. assert(0);
  1176. }
  1177. }
  1178. static void emit_store(cg_codegen_t * gen, cg_inst_store_t * inst)
  1179. {
  1180. switch (inst->base.opcode)
  1181. {
  1182. case cg_op_stb:
  1183. switch (inst->base.kind)
  1184. {
  1185. case cg_inst_store:
  1186. ARM_STRB_IMM(gen->cseg, inst->source->physical_reg->regno,
  1187. inst->mem.base->physical_reg->regno, 0);
  1188. break;
  1189. case cg_inst_arm_store_immed_offset:
  1190. ARM_STRB_IMM(gen->cseg, inst->source->physical_reg->regno,
  1191. inst->mem.immed_offset.base->physical_reg->regno,
  1192. inst->mem.immed_offset.offset);
  1193. break;
  1194. case cg_inst_arm_store_reg_offset:
  1195. ARM_STRB_REG_REG(gen->cseg, inst->source->physical_reg->regno,
  1196. inst->mem.reg_offset.base->physical_reg->regno,
  1197. inst->mem.reg_offset.offset->physical_reg->regno);
  1198. break;
  1199. default:
  1200. assert(0);
  1201. }
  1202. break;
  1203. case cg_op_sth:
  1204. switch (inst->base.kind)
  1205. {
  1206. case cg_inst_store:
  1207. ARM_STRH_IMM(gen->cseg, inst->source->physical_reg->regno,
  1208. inst->mem.base->physical_reg->regno, 0);
  1209. break;
  1210. case cg_inst_arm_store_immed_offset:
  1211. ARM_STRH_IMM(gen->cseg, inst->source->physical_reg->regno,
  1212. inst->mem.immed_offset.base->physical_reg->regno,
  1213. inst->mem.immed_offset.offset);
  1214. break;
  1215. case cg_inst_arm_store_reg_offset:
  1216. ARM_STRH_REG_REG(gen->cseg, inst->source->physical_reg->regno,
  1217. inst->mem.reg_offset.base->physical_reg->regno,
  1218. inst->mem.reg_offset.offset->physical_reg->regno);
  1219. break;
  1220. default:
  1221. assert(0);
  1222. }
  1223. break;
  1224. case cg_op_stw:
  1225. switch (inst->base.kind)
  1226. {
  1227. case cg_inst_store:
  1228. ARM_STR_IMM(gen->cseg, inst->source->physical_reg->regno,
  1229. inst->mem.base->physical_reg->regno, 0);
  1230. break;
  1231. case cg_inst_arm_store_immed_offset:
  1232. ARM_STR_IMM(gen->cseg, inst->source->physical_reg->regno,
  1233. inst->mem.immed_offset.base->physical_reg->regno,
  1234. inst->mem.immed_offset.offset);
  1235. break;
  1236. case cg_inst_arm_store_reg_offset:
  1237. ARM_STR_REG_REG(gen->cseg, inst->source->physical_reg->regno,
  1238. inst->mem.reg_offset.base->physical_reg->regno,
  1239. inst->mem.reg_offset.offset->physical_reg->regno);
  1240. break;
  1241. default:
  1242. assert(0);
  1243. }
  1244. break;
  1245. default:
  1246. assert(0);
  1247. }
  1248. }
  1249. static void emit_load_immediate(cg_codegen_t * gen,
  1250. cg_inst_load_immed_t * inst)
  1251. {
  1252. assert(inst->base.opcode == cg_op_ldi);
  1253. arm_mov_reg_imm32(gen->cseg, inst->dest->physical_reg->regno,
  1254. inst->value);
  1255. }
  1256. static void flush_dirty_regs(cg_codegen_t * gen, cg_bitset_t * live);
  1257. static void flush_dirty_args(cg_codegen_t * gen);
  1258. static void emit_branch(cg_codegen_t * gen, cg_inst_branch_t * inst)
  1259. {
  1260. ARMCond cond;
  1261. flush_dirty_regs(gen, inst->target->block->live_in);
  1262. switch (inst->base.kind)
  1263. {
  1264. case cg_inst_branch_label:
  1265. assert(inst->base.opcode == cg_op_bra);
  1266. branch(gen, inst->target->block->label);
  1267. return;
  1268. case cg_inst_branch_cond:
  1269. /* ensure condition flag is bound to virtual reg. */
  1270. switch (inst->base.opcode)
  1271. {
  1272. case cg_op_beq: cond = ARMCOND_EQ; break;
  1273. case cg_op_bge: cond = ARMCOND_GE; break;
  1274. case cg_op_ble: cond = ARMCOND_LE; break;
  1275. case cg_op_bgt: cond = ARMCOND_GT; break;
  1276. case cg_op_blt: cond = ARMCOND_LT; break;
  1277. case cg_op_bne: cond = ARMCOND_NE; break;
  1278. case cg_op_bra: cond = ARMCOND_AL; break;
  1279. case cg_op_nop: cond = ARMCOND_NV; break;
  1280. default:
  1281. assert(0);
  1282. }
  1283. branch_cond(gen, inst->target->block->label, cond);
  1284. break;
  1285. default:
  1286. assert(0);
  1287. }
  1288. }
  1289. static void emit_call(cg_codegen_t * gen, cg_inst_call_t * inst)
  1290. {
  1291. call(gen, inst->proc->prologue, inst->args, (cg_inst_t *) inst);
  1292. // deal with results
  1293. if (inst->dest)
  1294. {
  1295. cg_physical_reg_t * physical_reg = allocate_reg(gen, inst->dest, 1 << ARMREG_A1);
  1296. assign_reg(gen, physical_reg, inst->dest);
  1297. physical_reg->dirty = physical_reg->defined = 1;
  1298. }
  1299. }
  1300. static void emit_ret(cg_codegen_t * gen, cg_inst_ret_t * inst)
  1301. {
  1302. if (inst->result)
  1303. {
  1304. /********************************************************************/
  1305. /* Make sure that result is in correct register */
  1306. /********************************************************************/
  1307. if (inst->result->physical_reg->regno != ARMREG_A1)
  1308. {
  1309. ARM_MOV_REG_REG(gen->cseg, ARMREG_A1,
  1310. inst->result->physical_reg->regno);
  1311. }
  1312. }
  1313. if (inst->base.next || inst->base.block->next)
  1314. {
  1315. /* if this is not the last instruction in its block, and it's not the last block of the procedure */
  1316. branch(gen, inst->base.block->proc->epilogue);
  1317. }
  1318. }
  1319. static void dispatch_inst(cg_codegen_t * gen, cg_inst_t * inst, int update_flags)
  1320. {
  1321. switch (inst->base.kind)
  1322. {
  1323. case cg_inst_unary:
  1324. case cg_inst_arm_unary_immed:
  1325. case cg_inst_arm_unary_shift_reg:
  1326. case cg_inst_arm_unary_shift_immed:
  1327. emit_unary(gen, &inst->unary, update_flags);
  1328. break;
  1329. case cg_inst_binary:
  1330. case cg_inst_arm_binary_immed:
  1331. case cg_inst_arm_binary_shift_reg:
  1332. case cg_inst_arm_binary_shift_immed:
  1333. emit_binary(gen, &inst->binary, update_flags);
  1334. break;
  1335. case cg_inst_compare:
  1336. case cg_inst_arm_compare_immed:
  1337. case cg_inst_arm_compare_shift_reg:
  1338. case cg_inst_arm_compare_shift_immed:
  1339. emit_compare(gen, &inst->compare);
  1340. break;
  1341. case cg_inst_load:
  1342. case cg_inst_arm_load_immed_offset:
  1343. case cg_inst_arm_load_reg_offset:
  1344. emit_load(gen, &inst->load);
  1345. break;
  1346. case cg_inst_store:
  1347. case cg_inst_arm_store_immed_offset:
  1348. case cg_inst_arm_store_reg_offset:
  1349. emit_store(gen, &inst->store);
  1350. break;
  1351. case cg_inst_load_immed:
  1352. emit_load_immediate(gen, &inst->immed);
  1353. break;
  1354. case cg_inst_branch_label:
  1355. case cg_inst_branch_cond:
  1356. emit_branch(gen, &inst->branch);
  1357. break;
  1358. case cg_inst_call:
  1359. emit_call(gen, &inst->call);
  1360. break;
  1361. case cg_inst_ret:
  1362. emit_ret(gen, &inst->ret);
  1363. break;
  1364. // ARM specific formats
  1365. case cg_inst_phi:
  1366. default:
  1367. assert(0);
  1368. }
  1369. }
  1370. static cg_physical_reg_t * spill_candidate(cg_codegen_t * gen,
  1371. cg_virtual_reg_t * reg, U32 mask)
  1372. /************************************************************************/
  1373. /* Determine a spill candidate because we need a register for the given */
  1374. /* virtual register */
  1375. /************************************************************************/
  1376. {
  1377. // pick the register whose next use is most far away
  1378. // if possible, select a register that is not dirty
  1379. cg_physical_reg_t * physical_reg = gen->used_regs.tail;
  1380. while (physical_reg != 0 &&
  1381. !((1u << physical_reg->regno) & mask))
  1382. {
  1383. physical_reg = physical_reg->prev;
  1384. }
  1385. return physical_reg;
  1386. }
  1387. static I32 fp_offset(cg_codegen_t * gen, cg_virtual_reg_t * reg) {
  1388. if (reg->fp_offset == ~0) {
  1389. if (reg->representative->fp_offset == ~0)
  1390. {
  1391. cg_proc_t * proc = gen->current_block->proc;
  1392. proc->local_storage += sizeof(U32);
  1393. reg->representative->fp_offset = - (int) proc->local_storage - SAVE_AREA_SIZE;
  1394. }
  1395. reg->fp_offset = reg->representative->fp_offset;
  1396. }
  1397. return reg->fp_offset;
  1398. }
  1399. static void save_reg(cg_codegen_t * gen, cg_physical_reg_t * physical_reg,
  1400. cg_virtual_reg_t * reg)
  1401. /************************************************************************/
  1402. /* Save a given physical register */
  1403. /************************************************************************/
  1404. {
  1405. assert(physical_reg->dirty);
  1406. // generate code to save the register; reg -> FP + offset
  1407. ARM_STR_IMM(gen->cseg, physical_reg->regno, ARMREG_FP,
  1408. fp_offset(gen, reg));
  1409. physical_reg->dirty = 0;
  1410. }
  1411. static void restore_reg(cg_codegen_t * gen, cg_physical_reg_t * physical_reg,
  1412. cg_virtual_reg_t * reg)
  1413. /************************************************************************/
  1414. /* Restore a given physical register */
  1415. /************************************************************************/
  1416. {
  1417. assert(!physical_reg->defined);
  1418. // generate code to save the register; FP + offset -> reg
  1419. ARM_LDR_IMM(gen->cseg, physical_reg->regno, ARMREG_FP,
  1420. fp_offset(gen, reg));
  1421. physical_reg->defined = 1;
  1422. }
  1423. static void deallocate_reg(cg_codegen_t * gen, cg_physical_reg_t * physical_reg)
  1424. /************************************************************************/
  1425. /* free up a register because it is no longer used */
  1426. /************************************************************************/
  1427. {
  1428. cg_virtual_reg_t * reg = physical_reg->virtual_reg;
  1429. int used;
  1430. if (reg != 0 && reg->physical_reg == physical_reg)
  1431. {
  1432. //reg->physical_reg = (cg_physical_reg_t *) 0;
  1433. used = CG_BITSET_TEST(gen->current_block->live_out, reg->reg_no) ||
  1434. gen->use_chains[reg->reg_no];
  1435. if (physical_reg->dirty && used)
  1436. {
  1437. save_reg(gen, physical_reg, reg);
  1438. }
  1439. }
  1440. physical_reg->virtual_reg = (cg_virtual_reg_t *) 0;
  1441. if (physical_reg->list == &gen->used_regs)
  1442. {
  1443. reg_list_remove(&gen->used_regs, physical_reg);
  1444. reg_list_add(&gen->free_regs, physical_reg);
  1445. }
  1446. assert(physical_reg->list == &gen->free_regs);
  1447. physical_reg->dirty = physical_reg->defined = 0;
  1448. }
  1449. static cg_physical_reg_t * allocate_reg(cg_codegen_t * gen, cg_virtual_reg_t * reg,
  1450. U32 mask)
  1451. /************************************************************************/
  1452. /* Allocate a specific physical register for a virtual register */
  1453. /************************************************************************/
  1454. {
  1455. cg_physical_reg_t * physical_reg;
  1456. if (mask == 0)
  1457. {
  1458. mask = ~0u;
  1459. }
  1460. // check if the virtual register is already present in a matching
  1461. // physical register
  1462. // if so, return that register
  1463. if (reg->representative)
  1464. physical_reg = reg->representative->physical_reg;
  1465. else
  1466. physical_reg = reg->physical_reg;
  1467. if (physical_reg != 0 && physical_reg->virtual_reg && physical_reg->virtual_reg->representative == reg->representative &&
  1468. ((1u << physical_reg->regno) & mask))
  1469. {
  1470. reg_list_move_to_front(physical_reg->list, physical_reg);
  1471. return physical_reg;
  1472. }
  1473. physical_reg = gen->free_regs.tail;
  1474. while (physical_reg)
  1475. {
  1476. if ((1u << physical_reg->regno) & mask)
  1477. {
  1478. reg_list_remove(&gen->free_regs, physical_reg);
  1479. reg_list_add(&gen->used_regs, physical_reg);
  1480. return physical_reg;
  1481. }
  1482. physical_reg = physical_reg->prev;
  1483. }
  1484. // determine a spill candidate
  1485. physical_reg = spill_candidate(gen, reg, mask);
  1486. assert(physical_reg->list == &gen->used_regs);
  1487. deallocate_reg(gen, physical_reg);
  1488. assert(physical_reg->list == &gen->free_regs);
  1489. reg_list_remove(&gen->free_regs, physical_reg);
  1490. reg_list_add(&gen->used_regs, physical_reg);
  1491. return physical_reg;
  1492. }
  1493. static void assign_reg(cg_codegen_t * gen,
  1494. cg_physical_reg_t * physical_reg,
  1495. cg_virtual_reg_t * reg)
  1496. /************************************************************************/
  1497. /* Bind a specific physical register to a virtual register */
  1498. /************************************************************************/
  1499. {
  1500. // associate the physical register with the virtual register
  1501. // but mark the register as no holding the value yet
  1502. if (physical_reg->virtual_reg != reg)
  1503. {
  1504. cg_virtual_reg_t * old_reg = physical_reg->virtual_reg;
  1505. physical_reg->virtual_reg = reg;
  1506. if (old_reg == NULL || reg->representative != old_reg->representative)
  1507. physical_reg->defined = physical_reg->dirty = 0;
  1508. }
  1509. if (reg->physical_reg == (cg_physical_reg_t *) 0 ||
  1510. reg->physical_reg->virtual_reg != reg)
  1511. {
  1512. reg->physical_reg = physical_reg;
  1513. }
  1514. }
  1515. static void ensure_loaded(cg_codegen_t * gen,
  1516. cg_physical_reg_t * physical_reg,
  1517. cg_virtual_reg_t * reg)
  1518. /************************************************************************/
  1519. /* Allocate a specific physical register for a virtual register */
  1520. /************************************************************************/
  1521. {
  1522. assert(physical_reg->virtual_reg == reg);
  1523. //assert(reg->physical_reg == physical_reg);
  1524. if (!physical_reg->defined)
  1525. {
  1526. if (reg->physical_reg != physical_reg && reg->physical_reg->defined)
  1527. {
  1528. reg_list_move_to_front(reg->physical_reg->list, reg->physical_reg);
  1529. ARM_MOV_REG_REG(gen->cseg, physical_reg->regno, reg->physical_reg->regno);
  1530. physical_reg->defined = 1;
  1531. }
  1532. else
  1533. {
  1534. assert(!physical_reg->dirty);
  1535. restore_reg(gen, physical_reg, reg);
  1536. assert(physical_reg->defined);
  1537. }
  1538. }
  1539. }
  1540. static void make_global(cg_codegen_t * gen, cg_physical_reg_t * reg)
  1541. {
  1542. assert(reg->virtual_reg->is_global);
  1543. assert(reg->list == &gen->used_regs);
  1544. reg_list_remove(reg->list, reg);
  1545. reg_list_add(&gen->global_regs, reg);
  1546. }
  1547. static cg_physical_reg_t * load_reg(cg_codegen_t * gen, cg_virtual_reg_t * reg,
  1548. U32 mask)
  1549. {
  1550. cg_physical_reg_t * physical_reg;
  1551. physical_reg = allocate_reg(gen, reg, mask);
  1552. assign_reg(gen, physical_reg, reg);
  1553. ensure_loaded(gen, physical_reg, reg);
  1554. return physical_reg;
  1555. }
  1556. void cg_codegen_emit_simple_inst(cg_codegen_t * gen, cg_inst_t * inst)
  1557. {
  1558. /************************************************************************/
  1559. /* Allocate registers for virtual registers in use set */
  1560. /************************************************************************/
  1561. cg_virtual_reg_t * buffer[64];
  1562. cg_virtual_reg_t **iter, ** end = cg_inst_use(inst, buffer, buffer + 64);
  1563. int update_flags = 0;
  1564. int prefetch_mask = ~0;
  1565. for (iter = buffer; iter != end; ++iter)
  1566. {
  1567. cg_virtual_reg_t * reg = *iter;
  1568. cg_physical_reg_t * physical_reg;
  1569. cg_inst_list_t ** plist = &gen->use_chains[reg->reg_no];
  1570. while (*plist != (cg_inst_list_t *) 0 &&
  1571. (*plist)->inst != inst)
  1572. {
  1573. plist = &(*plist)->next;
  1574. }
  1575. if (*plist != 0)
  1576. {
  1577. *plist = (*plist)->next;
  1578. }
  1579. if (reg->type == cg_reg_type_flags)
  1580. {
  1581. /****************************************************************/
  1582. /* do not allocate a register for flags, however we will have */
  1583. /* to add spill code later */
  1584. /****************************************************************/
  1585. if (gen->flags.virtual_reg == reg)
  1586. continue; /* OK, current value is what we need */
  1587. if (reg->physical_reg != NULL &&
  1588. reg->physical_reg->virtual_reg == reg)
  1589. {
  1590. // value is in a regular register
  1591. restore_flags(gen, reg->physical_reg);
  1592. gen->flags.virtual_reg = reg;
  1593. continue;
  1594. }
  1595. physical_reg = load_reg(gen, reg, 0);
  1596. restore_flags(gen, physical_reg);
  1597. deallocate_reg(gen, physical_reg);
  1598. gen->flags.virtual_reg = reg;
  1599. continue;
  1600. }
  1601. physical_reg = load_reg(gen, reg, 0);
  1602. prefetch_mask &= ~physical_reg->regno;
  1603. }
  1604. /************************************************************************/
  1605. /* Free up any register that won't be needed after the completion of */
  1606. /* the current instruction */
  1607. /************************************************************************/
  1608. for (iter = buffer; iter != end; ++iter)
  1609. {
  1610. cg_virtual_reg_t * reg = *iter;
  1611. if (!reg->is_global && !reg->representative->is_global &&
  1612. reg->type != cg_reg_type_flags &&
  1613. gen->use_chains[reg->reg_no] == (cg_inst_list_t *) 0)
  1614. {
  1615. deallocate_reg(gen, reg->physical_reg);
  1616. }
  1617. }
  1618. /************************************************************************/
  1619. /* Allocate registers for all registers in def set */
  1620. /************************************************************************/
  1621. end = cg_inst_def(inst, buffer, buffer + 64);
  1622. for (iter = buffer; iter != end; ++iter)
  1623. {
  1624. // for each def:
  1625. // allocate a new register
  1626. cg_virtual_reg_t * reg = *iter;
  1627. cg_physical_reg_t * physical_reg;
  1628. if (reg->type == cg_reg_type_flags)
  1629. {
  1630. /****************************************************************/
  1631. /* do not allocate a register for flags, but save flags if they */
  1632. /* are needed later */
  1633. /****************************************************************/
  1634. update_flags = 1;
  1635. if (gen->flags.virtual_reg != NULL)
  1636. {
  1637. cg_virtual_reg_t * old_reg = gen->flags.virtual_reg;
  1638. int used = CG_BITSET_TEST(gen->current_block->live_out, old_reg->reg_no) ||
  1639. gen->use_chains[old_reg->reg_no];
  1640. if (used)
  1641. {
  1642. physical_reg = allocate_reg(gen, gen->flags.virtual_reg, 0);
  1643. assign_reg(gen, physical_reg, gen->flags.virtual_reg);
  1644. save_flags(gen, physical_reg);
  1645. physical_reg->dirty = physical_reg->defined = 1;
  1646. prefetch_mask &= ~physical_reg->regno;
  1647. }
  1648. }
  1649. gen->flags.virtual_reg = reg;
  1650. reg->physical_reg = &gen->flags;
  1651. continue;
  1652. }
  1653. physical_reg = allocate_reg(gen, reg, 0);
  1654. assign_reg(gen, physical_reg, reg);
  1655. prefetch_mask &= ~physical_reg->regno;
  1656. }
  1657. #if 0
  1658. /*
  1659. ** At this point, we might want to check for potential preloads
  1660. */
  1661. if (inst->base.next && is_simple_inst(inst->base.next))
  1662. {
  1663. /********************************************************************/
  1664. /* At this point, we might want to check for potential preloads */
  1665. /********************************************************************/
  1666. cg_inst_t * next = inst->base.next;
  1667. cg_virtual_reg_t * buffer_next[64];
  1668. cg_virtual_reg_t **iter_next, ** end_next =
  1669. cg_inst_use(next, buffer_next, buffer_next + 64);
  1670. // check if this instruction has dependencies on values that are
  1671. // not defined by the present instruction, and that currently do
  1672. // not reside in registers.
  1673. for (iter_next = buffer_next; iter_next != end_next; ++iter_next)
  1674. {
  1675. cg_virtual_reg_t * reg = *iter_next;
  1676. if (reg->type != cg_reg_type_general)
  1677. {
  1678. /* not general register or direct dependency on current */
  1679. /* instruction -> skip */
  1680. continue;
  1681. }
  1682. for (iter = buffer; iter != end; ++iter)
  1683. {
  1684. cg_virtual_reg_t * def_reg = *iter;
  1685. if (def_reg->representative == reg->representative)
  1686. goto next_iter;
  1687. }
  1688. if (reg->physical_reg != NULL && reg->physical_reg->virtual_reg != 0)
  1689. {
  1690. /* value already/still in physical register -> skip */
  1691. continue;
  1692. }
  1693. load_reg(gen, reg, prefetch_mask);
  1694. next_iter:
  1695. ;
  1696. }
  1697. }
  1698. #endif
  1699. dispatch_inst(gen, inst, update_flags);
  1700. /************************************************************************/
  1701. /* Mark all registers from the def set as dirty and defined */
  1702. /************************************************************************/
  1703. for (iter = buffer; iter != end; ++iter)
  1704. {
  1705. cg_virtual_reg_t * reg = *iter;
  1706. cg_physical_reg_t * physical_reg;
  1707. physical_reg = reg->physical_reg;
  1708. physical_reg->dirty = physical_reg->defined = 1;
  1709. }
  1710. }
  1711. void cg_codegen_emit_inst(cg_codegen_t * gen, cg_inst_t * inst)
  1712. {
  1713. switch (inst->base.opcode)
  1714. {
  1715. case cg_op_finv:
  1716. {
  1717. cg_physical_reg_t * physical_reg;
  1718. load_register_arg(gen, inst->unary.operand.source, ARMREG_A1, inst);
  1719. kill_flags(gen);
  1720. kill_argument_registers(gen);
  1721. call_runtime(gen, gen->runtime->inv_LP_16_32s);
  1722. /* load result from stack position */
  1723. physical_reg = allocate_reg(gen, inst->unary.dest_value, 1);
  1724. assign_reg(gen, physical_reg, inst->unary.dest_value);
  1725. physical_reg->dirty = physical_reg->defined = 1;
  1726. }
  1727. break;
  1728. case cg_op_fdiv:
  1729. {
  1730. cg_physical_reg_t * physical_reg;
  1731. load_register_arg(gen, inst->binary.source, ARMREG_A1, inst);
  1732. load_register_arg(gen, inst->binary.operand.source, ARMREG_A2, inst);
  1733. kill_flags(gen);
  1734. kill_argument_registers(gen);
  1735. call_runtime(gen, gen->runtime->div_LP_16_32s);
  1736. /* load result from stack position */
  1737. physical_reg = allocate_reg(gen, inst->unary.dest_value, 1);
  1738. assign_reg(gen, physical_reg, inst->unary.dest_value);
  1739. physical_reg->dirty = physical_reg->defined = 1;
  1740. }
  1741. break;
  1742. case cg_op_fsqrt:
  1743. {
  1744. cg_physical_reg_t * physical_reg;
  1745. load_register_arg(gen, inst->unary.operand.source, ARMREG_A1, inst);
  1746. kill_flags(gen);
  1747. kill_argument_registers(gen);
  1748. call_runtime(gen, gen->runtime->sqrt_LP_16_32s);
  1749. /* load result from stack position */
  1750. physical_reg = allocate_reg(gen, inst->unary.dest_value, 1);
  1751. assign_reg(gen, physical_reg, inst->unary.dest_value);
  1752. physical_reg->dirty = physical_reg->defined = 1;
  1753. }
  1754. break;
  1755. case cg_op_div:
  1756. {
  1757. cg_physical_reg_t * physical_reg;
  1758. load_register_arg(gen, inst->binary.source, ARMREG_A2, inst);
  1759. load_register_arg(gen, inst->binary.operand.source, ARMREG_A3, inst);
  1760. kill_flags(gen);
  1761. kill_argument_registers(gen);
  1762. ARM_SUB_REG_IMM8(gen->cseg, ARMREG_SP, ARMREG_SP, sizeof(div_t));
  1763. ARM_MOV_REG_REG(gen->cseg, ARMREG_A1, ARMREG_SP);
  1764. call_runtime(gen, gen->runtime->div);
  1765. /* load result from stack position */
  1766. physical_reg = allocate_reg(gen, inst->unary.dest_value, 0);
  1767. assign_reg(gen, physical_reg, inst->unary.dest_value);
  1768. physical_reg->dirty = physical_reg->defined = 1;
  1769. ARM_LDR_IMM(gen->cseg, physical_reg->regno, ARMREG_SP, offsetof(div_t, quot));
  1770. ARM_ADD_REG_IMM8(gen->cseg, ARMREG_SP, ARMREG_SP, sizeof(div_t));
  1771. }
  1772. break;
  1773. case cg_op_mod:
  1774. {
  1775. cg_physical_reg_t * physical_reg;
  1776. load_register_arg(gen, inst->binary.source, ARMREG_A2, inst);
  1777. load_register_arg(gen, inst->binary.operand.source, ARMREG_A3, inst);
  1778. kill_flags(gen);
  1779. kill_argument_registers(gen);
  1780. ARM_SUB_REG_IMM8(gen->cseg, ARMREG_SP, ARMREG_SP, sizeof(div_t));
  1781. ARM_MOV_REG_REG(gen->cseg, ARMREG_A1, ARMREG_SP);
  1782. call_runtime(gen, gen->runtime->div);
  1783. /* load result from stack position */
  1784. physical_reg = allocate_reg(gen, inst->unary.dest_value, 0);
  1785. assign_reg(gen, physical_reg, inst->unary.dest_value);
  1786. physical_reg->dirty = physical_reg->defined = 1;
  1787. ARM_LDR_IMM(gen->cseg, physical_reg->regno, ARMREG_SP, offsetof(div_t, rem));
  1788. ARM_ADD_REG_IMM8(gen->cseg, ARMREG_SP, ARMREG_SP, sizeof(div_t));
  1789. }
  1790. break;
  1791. case cg_op_call:
  1792. emit_call(gen, &inst->call);
  1793. break;
  1794. default:
  1795. cg_codegen_emit_simple_inst(gen, inst);
  1796. }
  1797. }
  1798. /****************************************************************************/
  1799. /* Processing of individual basic blocks */
  1800. /****************************************************************************/
  1801. static void init_flags(cg_codegen_t * gen)
  1802. {
  1803. /* clean out any association between flags and virtual registers */
  1804. gen->flags.prev = gen->flags.next = (cg_physical_reg_t *) 0;
  1805. gen->flags.virtual_reg = (cg_virtual_reg_t *) 0;
  1806. gen->flags.next_use = (cg_inst_t *) 0;
  1807. gen->flags.dirty = gen->flags.defined = 0;
  1808. }
  1809. static void allocate_globals(cg_codegen_t * gen)
  1810. {
  1811. cg_block_t * block = gen->current_block;
  1812. cg_proc_t * proc = block->proc;
  1813. cg_virtual_reg_list_t * node;
  1814. for (node = proc->globals; node; node = node->next)
  1815. {
  1816. if (CG_BITSET_TEST(block->live_in, node->reg->reg_no))
  1817. {
  1818. cg_virtual_reg_t * reg = node->reg;
  1819. cg_physical_reg_t * physical_reg = reg->physical_reg;
  1820. assert(physical_reg->list == &gen->free_regs);
  1821. reg_list_remove(physical_reg->list, physical_reg);
  1822. assign_reg(gen, physical_reg, node->reg);
  1823. reg_list_add(&gen->global_regs, physical_reg);
  1824. physical_reg->defined = 1;
  1825. }
  1826. else if (CG_BITSET_TEST(block->live_out, node->reg->reg_no))
  1827. {
  1828. cg_virtual_reg_t * reg = node->reg;
  1829. cg_physical_reg_t * physical_reg = reg->physical_reg;
  1830. assert(physical_reg->list == &gen->free_regs);
  1831. reg_list_remove(physical_reg->list, physical_reg);
  1832. assign_reg(gen, physical_reg, node->reg);
  1833. reg_list_add(&gen->global_regs, physical_reg);
  1834. physical_reg->defined = 0;
  1835. }
  1836. }
  1837. }
  1838. static void begin_block(cg_codegen_t * gen)
  1839. {
  1840. /* these assertions will change as soon as we preserve globals */
  1841. /* across basic blocks in registers */
  1842. assert(gen->used_regs.head == (cg_physical_reg_t *) 0);
  1843. assert(gen->used_regs.tail == (cg_physical_reg_t *) 0);
  1844. assert(gen->global_regs.head == (cg_physical_reg_t *) 0);
  1845. assert(gen->global_regs.tail == (cg_physical_reg_t *) 0);
  1846. }
  1847. static void end_block(cg_codegen_t * gen)
  1848. {
  1849. /* deallocate all registers */
  1850. while (gen->used_regs.tail != (cg_physical_reg_t *) 0)
  1851. {
  1852. cg_physical_reg_t * physical_reg = gen->used_regs.tail;
  1853. if (physical_reg->virtual_reg != NULL &&
  1854. physical_reg->virtual_reg->physical_reg == physical_reg)
  1855. {
  1856. deallocate_reg(gen, physical_reg);
  1857. }
  1858. else
  1859. {
  1860. reg_list_remove(&gen->used_regs, physical_reg);
  1861. reg_list_add(&gen->free_regs, physical_reg);
  1862. physical_reg->defined = physical_reg->dirty = 0;
  1863. physical_reg->virtual_reg = NULL;
  1864. }
  1865. }
  1866. while (gen->global_regs.tail != (cg_physical_reg_t *) 0)
  1867. {
  1868. cg_physical_reg_t * physical_reg = gen->global_regs.tail;
  1869. reg_list_remove(physical_reg->list, physical_reg);
  1870. reg_list_add(&gen->free_regs, physical_reg);
  1871. physical_reg->defined = physical_reg->dirty = 0;
  1872. physical_reg->virtual_reg = NULL;
  1873. }
  1874. init_flags(gen);
  1875. }
  1876. static void flush_dirty_reg_set(cg_codegen_t * gen, size_t min_reg,
  1877. size_t max_reg, cg_bitset_t * live)
  1878. {
  1879. size_t regno;
  1880. for (regno = min_reg; regno <= max_reg; ++regno)
  1881. {
  1882. if (gen->registers[regno].dirty)
  1883. {
  1884. cg_virtual_reg_t * reg = gen->registers[regno].virtual_reg;
  1885. if (live == NULL ||
  1886. reg && !reg->is_global && !reg->representative->is_global &&
  1887. reg->physical_reg == &gen->registers[regno] &&
  1888. CG_BITSET_TEST(live, reg->reg_no))
  1889. {
  1890. save_reg(gen, &gen->registers[regno], reg);
  1891. }
  1892. }
  1893. }
  1894. }
  1895. static void flush_dirty_regs(cg_codegen_t * gen, cg_bitset_t * live)
  1896. {
  1897. flush_dirty_reg_set(gen, 0, PHYSICAL_REGISTERS - 1, live);
  1898. }
  1899. static void flush_dirty_args(cg_codegen_t * gen)
  1900. {
  1901. flush_dirty_reg_set(gen, ARMREG_A1, ARMREG_A4, NULL);
  1902. }
  1903. static void process_phi(cg_codegen_t * gen, cg_inst_phi_t * inst)
  1904. {
  1905. /* Any processing necessary for phi instructions */
  1906. }
  1907. static void init_use_chains(cg_codegen_t * gen, cg_block_t * block)
  1908. {
  1909. cg_inst_t * inst;
  1910. size_t num_registers = block->proc->num_registers;
  1911. size_t regno;
  1912. cg_inst_list_t *** p_head =
  1913. (cg_inst_list_t ***) malloc(sizeof(cg_inst_list_t **) * num_registers);
  1914. for (regno = 0; regno != num_registers; ++regno)
  1915. {
  1916. p_head[regno] = &gen->use_chains[regno];
  1917. gen->use_chains[regno] = (cg_inst_list_t *) 0;
  1918. }
  1919. for (inst = block->insts.head; inst != (cg_inst_t *) 0; inst = inst->base.next)
  1920. {
  1921. cg_virtual_reg_t * buffer[64];
  1922. cg_virtual_reg_t **iter, ** end = cg_inst_use(inst, buffer, buffer + 64);
  1923. for (iter = buffer; iter != end; ++iter)
  1924. {
  1925. cg_inst_list_t * node = (cg_inst_list_t *)
  1926. cg_heap_allocate(gen->heap, sizeof(cg_inst_list_t));
  1927. regno = (*iter)->reg_no;
  1928. *p_head[regno] = node;
  1929. node->inst = inst;
  1930. p_head[regno] = &node->next;
  1931. }
  1932. }
  1933. free(p_head);
  1934. }
  1935. void cg_codegen_emit_block(cg_codegen_t * gen, cg_block_t * block, int reinit)
  1936. {
  1937. cg_inst_t * inst;
  1938. gen->current_block = block;
  1939. cg_codegen_define(gen, block->label);
  1940. init_use_chains(gen, block);
  1941. if (reinit)
  1942. begin_block(gen);
  1943. allocate_globals(gen);
  1944. /************************************************************************/
  1945. /* Process and skip any phi mappings at beginning of block */
  1946. /************************************************************************/
  1947. for (inst = block->insts.head;
  1948. inst != (cg_inst_t *) 0 && inst->base.kind == cg_inst_phi;
  1949. inst = inst->base.next)
  1950. {
  1951. process_phi(gen, &inst->phi);
  1952. }
  1953. /************************************************************************/
  1954. /* Emit actual basic block body */
  1955. /* This part will be replaced with a more sophisticed instruction */
  1956. /* scheduler */
  1957. /************************************************************************/
  1958. for (; inst != (cg_inst_t *) 0; inst = inst->base.next)
  1959. {
  1960. cg_codegen_emit_inst(gen, inst);
  1961. }
  1962. flush_dirty_regs(gen, block->live_out);
  1963. end_block(gen);
  1964. gen->current_block = (cg_block_t *) 0;
  1965. }
  1966. /****************************************************************************/
  1967. /* Processing of procedures */
  1968. /****************************************************************************/
  1969. static void init_arg(cg_codegen_t * gen, cg_physical_reg_t * physical_reg,
  1970. cg_virtual_reg_t * reg)
  1971. {
  1972. /************************************************************************/
  1973. /* init physical reg as physical register bound to reg, marked dirty */
  1974. /************************************************************************/
  1975. physical_reg->list = NULL;
  1976. physical_reg->prev = physical_reg->next = (cg_physical_reg_t *) 0;
  1977. physical_reg->virtual_reg = reg;
  1978. reg->physical_reg = physical_reg;
  1979. physical_reg->next_use = (cg_inst_t *) 0;
  1980. physical_reg->dirty = physical