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 23typedef struct TCGLabelPoolData { 24 struct TCGLabelPoolData *next; 25 tcg_insn_unit *label; 26 intptr_t addend; 27 int rtype; 28 unsigned nlong; 29 tcg_target_ulong data[]; 30} TCGLabelPoolData; 31 32 33static TCGLabelPoolData *new_pool_alloc(TCGContext *s, int nlong, int rtype, 34 tcg_insn_unit *label, intptr_t addend) 35{ 36 TCGLabelPoolData *n = tcg_malloc(sizeof(TCGLabelPoolData) 37 + sizeof(tcg_target_ulong) * nlong); 38 39 n->label = label; 40 n->addend = addend; 41 n->rtype = rtype; 42 n->nlong = nlong; 43 return n; 44} 45 46static void new_pool_insert(TCGContext *s, TCGLabelPoolData *n) 47{ 48 TCGLabelPoolData *i, **pp; 49 int nlong = n->nlong; 50 51 /* Insertion sort on the pool. */ 52 for (pp = &s->pool_labels; (i = *pp) != NULL; pp = &i->next) { 53 if (nlong > i->nlong) { 54 break; 55 } 56 if (nlong < i->nlong) { 57 continue; 58 } 59 if (memcmp(n->data, i->data, sizeof(tcg_target_ulong) * nlong) >= 0) { 60 break; 61 } 62 } 63 n->next = *pp; 64 *pp = n; 65} 66 67/* The "usual" for generic integer code. */ 68static inline void new_pool_label(TCGContext *s, tcg_target_ulong d, int rtype, 69 tcg_insn_unit *label, intptr_t addend) 70{ 71 TCGLabelPoolData *n = new_pool_alloc(s, 1, rtype, label, addend); 72 n->data[0] = d; 73 new_pool_insert(s, n); 74} 75 76/* For v64 or v128, depending on the host. */ 77static inline void new_pool_l2(TCGContext *s, int rtype, tcg_insn_unit *label, 78 intptr_t addend, tcg_target_ulong d0, 79 tcg_target_ulong d1) 80{ 81 TCGLabelPoolData *n = new_pool_alloc(s, 2, rtype, label, addend); 82 n->data[0] = d0; 83 n->data[1] = d1; 84 new_pool_insert(s, n); 85} 86 87/* For v128 or v256, depending on the host. */ 88static inline void new_pool_l4(TCGContext *s, int rtype, tcg_insn_unit *label, 89 intptr_t addend, tcg_target_ulong d0, 90 tcg_target_ulong d1, tcg_target_ulong d2, 91 tcg_target_ulong d3) 92{ 93 TCGLabelPoolData *n = new_pool_alloc(s, 4, rtype, label, addend); 94 n->data[0] = d0; 95 n->data[1] = d1; 96 n->data[2] = d2; 97 n->data[3] = d3; 98 new_pool_insert(s, n); 99} 100 101/* For v256, for 32-bit host. */ 102static inline void new_pool_l8(TCGContext *s, int rtype, tcg_insn_unit *label, 103 intptr_t addend, tcg_target_ulong d0, 104 tcg_target_ulong d1, tcg_target_ulong d2, 105 tcg_target_ulong d3, tcg_target_ulong d4, 106 tcg_target_ulong d5, tcg_target_ulong d6, 107 tcg_target_ulong d7) 108{ 109 TCGLabelPoolData *n = new_pool_alloc(s, 8, rtype, label, addend); 110 n->data[0] = d0; 111 n->data[1] = d1; 112 n->data[2] = d2; 113 n->data[3] = d3; 114 n->data[4] = d4; 115 n->data[5] = d5; 116 n->data[6] = d6; 117 n->data[7] = d7; 118 new_pool_insert(s, n); 119} 120 121/* To be provided by cpu/tcg-target.c.inc. */ 122static void tcg_out_nop_fill(tcg_insn_unit *p, int count); 123 124static int tcg_out_pool_finalize(TCGContext *s) 125{ 126 TCGLabelPoolData *p = s->pool_labels; 127 TCGLabelPoolData *l = NULL; 128 void *a; 129 130 if (p == NULL) { 131 return 0; 132 } 133 134 /* ??? Round up to qemu_icache_linesize, but then do not round 135 again when allocating the next TranslationBlock structure. */ 136 a = (void *)ROUND_UP((uintptr_t)s->code_ptr, 137 sizeof(tcg_target_ulong) * p->nlong); 138 tcg_out_nop_fill(s->code_ptr, (tcg_insn_unit *)a - s->code_ptr); 139 s->data_gen_ptr = a; 140 141 for (; p != NULL; p = p->next) { 142 size_t size = sizeof(tcg_target_ulong) * p->nlong; 143 uintptr_t value; 144 145 if (!l || l->nlong != p->nlong || memcmp(l->data, p->data, size)) { 146 if (unlikely(a > s->code_gen_highwater)) { 147 return -1; 148 } 149 memcpy(a, p->data, size); 150 a += size; 151 l = p; 152 } 153 154 value = (uintptr_t)tcg_splitwx_to_rx(a) - size; 155 if (!patch_reloc(p->label, p->rtype, value, p->addend)) { 156 return -2; 157 } 158 } 159 160 s->code_ptr = a; 161 return 0; 162} 163