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