tcg-pool.inc.c 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. /*
  2. * TCG Backend Data: constant pool.
  3. *
  4. * Permission is hereby granted, free of charge, to any person obtaining a copy
  5. * of this software and associated documentation files (the "Software"), to deal
  6. * in the Software without restriction, including without limitation the rights
  7. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  8. * copies of the Software, and to permit persons to whom the Software is
  9. * furnished to do so, subject to the following conditions:
  10. *
  11. * The above copyright notice and this permission notice shall be included in
  12. * all copies or substantial portions of the Software.
  13. *
  14. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  17. * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  19. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  20. * THE SOFTWARE.
  21. */
  22. typedef struct TCGLabelPoolData {
  23. struct TCGLabelPoolData *next;
  24. tcg_insn_unit *label;
  25. intptr_t addend;
  26. int rtype;
  27. unsigned nlong;
  28. tcg_target_ulong data[];
  29. } TCGLabelPoolData;
  30. static TCGLabelPoolData *new_pool_alloc(TCGContext *s, int nlong, int rtype,
  31. tcg_insn_unit *label, intptr_t addend)
  32. {
  33. TCGLabelPoolData *n = tcg_malloc(sizeof(TCGLabelPoolData)
  34. + sizeof(tcg_target_ulong) * nlong);
  35. n->label = label;
  36. n->addend = addend;
  37. n->rtype = rtype;
  38. n->nlong = nlong;
  39. return n;
  40. }
  41. static void new_pool_insert(TCGContext *s, TCGLabelPoolData *n)
  42. {
  43. TCGLabelPoolData *i, **pp;
  44. int nlong = n->nlong;
  45. /* Insertion sort on the pool. */
  46. for (pp = &s->pool_labels; (i = *pp) != NULL; pp = &i->next) {
  47. if (nlong > i->nlong) {
  48. break;
  49. }
  50. if (nlong < i->nlong) {
  51. continue;
  52. }
  53. if (memcmp(n->data, i->data, sizeof(tcg_target_ulong) * nlong) >= 0) {
  54. break;
  55. }
  56. }
  57. n->next = *pp;
  58. *pp = n;
  59. }
  60. /* The "usual" for generic integer code. */
  61. static inline void new_pool_label(TCGContext *s, tcg_target_ulong d, int rtype,
  62. tcg_insn_unit *label, intptr_t addend)
  63. {
  64. TCGLabelPoolData *n = new_pool_alloc(s, 1, rtype, label, addend);
  65. n->data[0] = d;
  66. new_pool_insert(s, n);
  67. }
  68. /* For v64 or v128, depending on the host. */
  69. static inline void new_pool_l2(TCGContext *s, int rtype, tcg_insn_unit *label,
  70. intptr_t addend, tcg_target_ulong d0,
  71. tcg_target_ulong d1)
  72. {
  73. TCGLabelPoolData *n = new_pool_alloc(s, 2, rtype, label, addend);
  74. n->data[0] = d0;
  75. n->data[1] = d1;
  76. new_pool_insert(s, n);
  77. }
  78. /* For v128 or v256, depending on the host. */
  79. static inline void new_pool_l4(TCGContext *s, int rtype, tcg_insn_unit *label,
  80. intptr_t addend, tcg_target_ulong d0,
  81. tcg_target_ulong d1, tcg_target_ulong d2,
  82. tcg_target_ulong d3)
  83. {
  84. TCGLabelPoolData *n = new_pool_alloc(s, 4, rtype, label, addend);
  85. n->data[0] = d0;
  86. n->data[1] = d1;
  87. n->data[2] = d2;
  88. n->data[3] = d3;
  89. new_pool_insert(s, n);
  90. }
  91. /* For v256, for 32-bit host. */
  92. static inline void new_pool_l8(TCGContext *s, int rtype, tcg_insn_unit *label,
  93. intptr_t addend, tcg_target_ulong d0,
  94. tcg_target_ulong d1, tcg_target_ulong d2,
  95. tcg_target_ulong d3, tcg_target_ulong d4,
  96. tcg_target_ulong d5, tcg_target_ulong d6,
  97. tcg_target_ulong d7)
  98. {
  99. TCGLabelPoolData *n = new_pool_alloc(s, 8, rtype, label, addend);
  100. n->data[0] = d0;
  101. n->data[1] = d1;
  102. n->data[2] = d2;
  103. n->data[3] = d3;
  104. n->data[4] = d4;
  105. n->data[5] = d5;
  106. n->data[6] = d6;
  107. n->data[7] = d7;
  108. new_pool_insert(s, n);
  109. }
  110. /* To be provided by cpu/tcg-target.inc.c. */
  111. static void tcg_out_nop_fill(TCGContext *s, tcg_insn_unit *p, int count);
  112. static int tcg_out_pool_finalize(TCGContext *s)
  113. {
  114. TCGLabelPoolData *p = s->pool_labels;
  115. TCGLabelPoolData *l = NULL;
  116. void *a;
  117. if (p == NULL) {
  118. return 0;
  119. }
  120. /* ??? Round up to qemu_icache_linesize, but then do not round
  121. again when allocating the next TranslationBlock structure. */
  122. a = (void *)ROUND_UP((uintptr_t)s->code_ptr,
  123. sizeof(tcg_target_ulong) * p->nlong);
  124. tcg_out_nop_fill(s, s->code_ptr, (tcg_insn_unit *)a - s->code_ptr);
  125. s->data_gen_ptr = a;
  126. for (; p != NULL; p = p->next) {
  127. size_t size = sizeof(tcg_target_ulong) * p->nlong;
  128. if (!l || l->nlong != p->nlong || memcmp(l->data, p->data, size)) {
  129. if (unlikely(a > s->code_gen_highwater)) {
  130. return -1;
  131. }
  132. memcpy(TCG_CODE_PTR_RW(s, a), p->data, size);
  133. a += size;
  134. l = p;
  135. }
  136. if (!patch_reloc(s, p->label, p->rtype,
  137. (intptr_t)a - size, p->addend)) {
  138. return -2;
  139. }
  140. }
  141. s->code_ptr = a;
  142. return 0;
  143. }