1139c1837SPaolo Bonzini/* 2139c1837SPaolo Bonzini * TCG Backend Data: constant pool. 3139c1837SPaolo Bonzini * 4139c1837SPaolo Bonzini * Permission is hereby granted, free of charge, to any person obtaining a copy 5139c1837SPaolo Bonzini * of this software and associated documentation files (the "Software"), to deal 6139c1837SPaolo Bonzini * in the Software without restriction, including without limitation the rights 7139c1837SPaolo Bonzini * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8139c1837SPaolo Bonzini * copies of the Software, and to permit persons to whom the Software is 9139c1837SPaolo Bonzini * furnished to do so, subject to the following conditions: 10139c1837SPaolo Bonzini * 11139c1837SPaolo Bonzini * The above copyright notice and this permission notice shall be included in 12139c1837SPaolo Bonzini * all copies or substantial portions of the Software. 13139c1837SPaolo Bonzini * 14139c1837SPaolo Bonzini * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15139c1837SPaolo Bonzini * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16139c1837SPaolo Bonzini * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17139c1837SPaolo Bonzini * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18139c1837SPaolo Bonzini * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19139c1837SPaolo Bonzini * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20139c1837SPaolo Bonzini * THE SOFTWARE. 21139c1837SPaolo Bonzini */ 22139c1837SPaolo Bonzini 23139c1837SPaolo Bonzinitypedef struct TCGLabelPoolData { 24139c1837SPaolo Bonzini struct TCGLabelPoolData *next; 25139c1837SPaolo Bonzini tcg_insn_unit *label; 26139c1837SPaolo Bonzini intptr_t addend; 27139c1837SPaolo Bonzini int rtype; 28139c1837SPaolo Bonzini unsigned nlong; 29139c1837SPaolo Bonzini tcg_target_ulong data[]; 30139c1837SPaolo Bonzini} TCGLabelPoolData; 31139c1837SPaolo Bonzini 32139c1837SPaolo Bonzini 33139c1837SPaolo Bonzinistatic TCGLabelPoolData *new_pool_alloc(TCGContext *s, int nlong, int rtype, 34139c1837SPaolo Bonzini tcg_insn_unit *label, intptr_t addend) 35139c1837SPaolo Bonzini{ 36139c1837SPaolo Bonzini TCGLabelPoolData *n = tcg_malloc(sizeof(TCGLabelPoolData) 37139c1837SPaolo Bonzini + sizeof(tcg_target_ulong) * nlong); 38139c1837SPaolo Bonzini 39139c1837SPaolo Bonzini n->label = label; 40139c1837SPaolo Bonzini n->addend = addend; 41139c1837SPaolo Bonzini n->rtype = rtype; 42139c1837SPaolo Bonzini n->nlong = nlong; 43139c1837SPaolo Bonzini return n; 44139c1837SPaolo Bonzini} 45139c1837SPaolo Bonzini 46139c1837SPaolo Bonzinistatic void new_pool_insert(TCGContext *s, TCGLabelPoolData *n) 47139c1837SPaolo Bonzini{ 48139c1837SPaolo Bonzini TCGLabelPoolData *i, **pp; 49139c1837SPaolo Bonzini int nlong = n->nlong; 50139c1837SPaolo Bonzini 51139c1837SPaolo Bonzini /* Insertion sort on the pool. */ 52139c1837SPaolo Bonzini for (pp = &s->pool_labels; (i = *pp) != NULL; pp = &i->next) { 53139c1837SPaolo Bonzini if (nlong > i->nlong) { 54139c1837SPaolo Bonzini break; 55139c1837SPaolo Bonzini } 56139c1837SPaolo Bonzini if (nlong < i->nlong) { 57139c1837SPaolo Bonzini continue; 58139c1837SPaolo Bonzini } 59139c1837SPaolo Bonzini if (memcmp(n->data, i->data, sizeof(tcg_target_ulong) * nlong) >= 0) { 60139c1837SPaolo Bonzini break; 61139c1837SPaolo Bonzini } 62139c1837SPaolo Bonzini } 63139c1837SPaolo Bonzini n->next = *pp; 64139c1837SPaolo Bonzini *pp = n; 65139c1837SPaolo Bonzini} 66139c1837SPaolo Bonzini 67139c1837SPaolo Bonzini/* The "usual" for generic integer code. */ 68139c1837SPaolo Bonzinistatic inline void new_pool_label(TCGContext *s, tcg_target_ulong d, int rtype, 69139c1837SPaolo Bonzini tcg_insn_unit *label, intptr_t addend) 70139c1837SPaolo Bonzini{ 71139c1837SPaolo Bonzini TCGLabelPoolData *n = new_pool_alloc(s, 1, rtype, label, addend); 72139c1837SPaolo Bonzini n->data[0] = d; 73139c1837SPaolo Bonzini new_pool_insert(s, n); 74139c1837SPaolo Bonzini} 75139c1837SPaolo Bonzini 76139c1837SPaolo Bonzini/* For v64 or v128, depending on the host. */ 77139c1837SPaolo Bonzinistatic inline void new_pool_l2(TCGContext *s, int rtype, tcg_insn_unit *label, 78139c1837SPaolo Bonzini intptr_t addend, tcg_target_ulong d0, 79139c1837SPaolo Bonzini tcg_target_ulong d1) 80139c1837SPaolo Bonzini{ 81139c1837SPaolo Bonzini TCGLabelPoolData *n = new_pool_alloc(s, 2, rtype, label, addend); 82139c1837SPaolo Bonzini n->data[0] = d0; 83139c1837SPaolo Bonzini n->data[1] = d1; 84139c1837SPaolo Bonzini new_pool_insert(s, n); 85139c1837SPaolo Bonzini} 86139c1837SPaolo Bonzini 87139c1837SPaolo Bonzini/* For v128 or v256, depending on the host. */ 88139c1837SPaolo Bonzinistatic inline void new_pool_l4(TCGContext *s, int rtype, tcg_insn_unit *label, 89139c1837SPaolo Bonzini intptr_t addend, tcg_target_ulong d0, 90139c1837SPaolo Bonzini tcg_target_ulong d1, tcg_target_ulong d2, 91139c1837SPaolo Bonzini tcg_target_ulong d3) 92139c1837SPaolo Bonzini{ 93139c1837SPaolo Bonzini TCGLabelPoolData *n = new_pool_alloc(s, 4, rtype, label, addend); 94139c1837SPaolo Bonzini n->data[0] = d0; 95139c1837SPaolo Bonzini n->data[1] = d1; 96139c1837SPaolo Bonzini n->data[2] = d2; 97139c1837SPaolo Bonzini n->data[3] = d3; 98139c1837SPaolo Bonzini new_pool_insert(s, n); 99139c1837SPaolo Bonzini} 100139c1837SPaolo Bonzini 101139c1837SPaolo Bonzini/* For v256, for 32-bit host. */ 102139c1837SPaolo Bonzinistatic inline void new_pool_l8(TCGContext *s, int rtype, tcg_insn_unit *label, 103139c1837SPaolo Bonzini intptr_t addend, tcg_target_ulong d0, 104139c1837SPaolo Bonzini tcg_target_ulong d1, tcg_target_ulong d2, 105139c1837SPaolo Bonzini tcg_target_ulong d3, tcg_target_ulong d4, 106139c1837SPaolo Bonzini tcg_target_ulong d5, tcg_target_ulong d6, 107139c1837SPaolo Bonzini tcg_target_ulong d7) 108139c1837SPaolo Bonzini{ 109139c1837SPaolo Bonzini TCGLabelPoolData *n = new_pool_alloc(s, 8, rtype, label, addend); 110139c1837SPaolo Bonzini n->data[0] = d0; 111139c1837SPaolo Bonzini n->data[1] = d1; 112139c1837SPaolo Bonzini n->data[2] = d2; 113139c1837SPaolo Bonzini n->data[3] = d3; 114139c1837SPaolo Bonzini n->data[4] = d4; 115139c1837SPaolo Bonzini n->data[5] = d5; 116139c1837SPaolo Bonzini n->data[6] = d6; 117139c1837SPaolo Bonzini n->data[7] = d7; 118139c1837SPaolo Bonzini new_pool_insert(s, n); 119139c1837SPaolo Bonzini} 120139c1837SPaolo Bonzini 121139c1837SPaolo Bonzini/* To be provided by cpu/tcg-target.c.inc. */ 122139c1837SPaolo Bonzinistatic void tcg_out_nop_fill(tcg_insn_unit *p, int count); 123139c1837SPaolo Bonzini 124139c1837SPaolo Bonzinistatic int tcg_out_pool_finalize(TCGContext *s) 125139c1837SPaolo Bonzini{ 126139c1837SPaolo Bonzini TCGLabelPoolData *p = s->pool_labels; 127139c1837SPaolo Bonzini TCGLabelPoolData *l = NULL; 128139c1837SPaolo Bonzini void *a; 129139c1837SPaolo Bonzini 130139c1837SPaolo Bonzini if (p == NULL) { 131139c1837SPaolo Bonzini return 0; 132139c1837SPaolo Bonzini } 133139c1837SPaolo Bonzini 134139c1837SPaolo Bonzini /* ??? Round up to qemu_icache_linesize, but then do not round 135139c1837SPaolo Bonzini again when allocating the next TranslationBlock structure. */ 136139c1837SPaolo Bonzini a = (void *)ROUND_UP((uintptr_t)s->code_ptr, 137139c1837SPaolo Bonzini sizeof(tcg_target_ulong) * p->nlong); 138139c1837SPaolo Bonzini tcg_out_nop_fill(s->code_ptr, (tcg_insn_unit *)a - s->code_ptr); 139139c1837SPaolo Bonzini s->data_gen_ptr = a; 140139c1837SPaolo Bonzini 141139c1837SPaolo Bonzini for (; p != NULL; p = p->next) { 142139c1837SPaolo Bonzini size_t size = sizeof(tcg_target_ulong) * p->nlong; 143*db0c51a3SRichard Henderson uintptr_t value; 144*db0c51a3SRichard Henderson 145139c1837SPaolo Bonzini if (!l || l->nlong != p->nlong || memcmp(l->data, p->data, size)) { 146139c1837SPaolo Bonzini if (unlikely(a > s->code_gen_highwater)) { 147139c1837SPaolo Bonzini return -1; 148139c1837SPaolo Bonzini } 149139c1837SPaolo Bonzini memcpy(a, p->data, size); 150139c1837SPaolo Bonzini a += size; 151139c1837SPaolo Bonzini l = p; 152139c1837SPaolo Bonzini } 153*db0c51a3SRichard Henderson 154*db0c51a3SRichard Henderson value = (uintptr_t)tcg_splitwx_to_rx(a) - size; 155*db0c51a3SRichard Henderson if (!patch_reloc(p->label, p->rtype, value, p->addend)) { 156139c1837SPaolo Bonzini return -2; 157139c1837SPaolo Bonzini } 158139c1837SPaolo Bonzini } 159139c1837SPaolo Bonzini 160139c1837SPaolo Bonzini s->code_ptr = a; 161139c1837SPaolo Bonzini return 0; 162139c1837SPaolo Bonzini} 163