qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

tcg-pool.c.inc (5387B)


      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 
     23 typedef 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 
     33 static 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 
     46 static 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.  */
     68 static 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.  */
     77 static 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.  */
     88 static 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.  */
    102 static 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.  */
    122 static void tcg_out_nop_fill(tcg_insn_unit *p, int count);
    123 
    124 static 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 }