Statistics
| Branch: | Revision:

root / dyngen.h @ 2c1794c4

History | View | Annotate | Download (5.1 kB)

1
/*
2
 * dyngen helpers
3
 * 
4
 *  Copyright (c) 2003 Fabrice Bellard
5
 *
6
 * This library is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU Lesser General Public
8
 * License as published by the Free Software Foundation; either
9
 * version 2 of the License, or (at your option) any later version.
10
 *
11
 * This library is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
 * Lesser General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU Lesser General Public
17
 * License along with this library; if not, write to the Free Software
18
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19
 */
20

    
21
int __op_param1, __op_param2, __op_param3;
22
int __op_jmp0, __op_jmp1;
23

    
24
#ifdef __i386__
25
static inline void flush_icache_range(unsigned long start, unsigned long stop)
26
{
27
}
28
#endif
29

    
30
#ifdef __s390__
31
static inline void flush_icache_range(unsigned long start, unsigned long stop)
32
{
33
}
34
#endif
35

    
36
#ifdef __ia64__
37
static inline void flush_icache_range(unsigned long start, unsigned long stop)
38
{
39
}
40
#endif
41

    
42
#ifdef __powerpc__
43

    
44
#define MIN_CACHE_LINE_SIZE 8 /* conservative value */
45

    
46
static void inline flush_icache_range(unsigned long start, unsigned long stop)
47
{
48
    unsigned long p;
49

    
50
    p = start & ~(MIN_CACHE_LINE_SIZE - 1);
51
    stop = (stop + MIN_CACHE_LINE_SIZE - 1) & ~(MIN_CACHE_LINE_SIZE - 1);
52
    
53
    for (p = start; p < stop; p += MIN_CACHE_LINE_SIZE) {
54
        asm volatile ("dcbst 0,%0" : : "r"(p) : "memory");
55
    }
56
    asm volatile ("sync" : : : "memory");
57
    for (p = start; p < stop; p += MIN_CACHE_LINE_SIZE) {
58
        asm volatile ("icbi 0,%0" : : "r"(p) : "memory");
59
    }
60
    asm volatile ("sync" : : : "memory");
61
    asm volatile ("isync" : : : "memory");
62
}
63
#endif
64

    
65
#ifdef __alpha__
66
static inline void flush_icache_range(unsigned long start, unsigned long stop)
67
{
68
    asm ("imb");
69
}
70
#endif
71

    
72
#ifdef __sparc__
73

    
74
static void inline flush_icache_range(unsigned long start, unsigned long stop)
75
{
76
        unsigned long p;
77

    
78
        p = start & ~(8UL - 1UL);
79
        stop = (stop + (8UL - 1UL)) & ~(8UL - 1UL);
80

    
81
        for (; p < stop; p += 8)
82
                __asm__ __volatile__("flush\t%0" : : "r" (p));
83
}
84

    
85
#endif
86

    
87
#ifdef __arm__
88
static inline void flush_icache_range(unsigned long start, unsigned long stop)
89
{
90
    register unsigned long _beg __asm ("a1") = start;
91
    register unsigned long _end __asm ("a2") = stop;
92
    register unsigned long _flg __asm ("a3") = 0;
93
    __asm __volatile__ ("swi 0x9f0002" : : "r" (_beg), "r" (_end), "r" (_flg));
94
}
95
#endif
96

    
97
#ifdef __alpha__
98

    
99
register int gp asm("$29");
100

    
101
static inline void immediate_ldah(void *p, int val) {
102
    uint32_t *dest = p;
103
    long high = ((val >> 16) + ((val >> 15) & 1)) & 0xffff;
104

    
105
    *dest &= ~0xffff;
106
    *dest |= high;
107
    *dest |= 31 << 16;
108
}
109
static inline void immediate_lda(void *dest, int val) {
110
    *(uint16_t *) dest = val;
111
}
112
void fix_bsr(void *p, int offset) {
113
    uint32_t *dest = p;
114
    *dest &= ~((1 << 21) - 1);
115
    *dest |= (offset >> 2) & ((1 << 21) - 1);
116
}
117

    
118
#endif /* __alpha__ */
119

    
120
#ifdef __arm__
121

    
122
#define MAX_OP_SIZE    (128 * 4) /* in bytes */
123
/* max size of the code that can be generated without calling arm_flush_ldr */
124
#define MAX_FRAG_SIZE  (1024 * 4) 
125
//#define MAX_FRAG_SIZE  (135 * 4) /* for testing */ 
126

    
127
typedef struct LDREntry {
128
    uint8_t *ptr;
129
    uint32_t *data_ptr;
130
} LDREntry;
131

    
132
static LDREntry arm_ldr_table[1024];
133
static uint32_t arm_data_table[1024];
134

    
135
extern char exec_loop;
136

    
137
static inline void arm_reloc_pc24(uint32_t *ptr, uint32_t insn, int val)
138
{
139
    *ptr = (insn & ~0xffffff) | ((insn + ((val - (int)ptr) >> 2)) & 0xffffff);
140
}
141

    
142
static uint8_t *arm_flush_ldr(uint8_t *gen_code_ptr,
143
                              LDREntry *ldr_start, LDREntry *ldr_end, 
144
                              uint32_t *data_start, uint32_t *data_end, 
145
                              int gen_jmp)
146
{
147
    LDREntry *le;
148
    uint32_t *ptr;
149
    int offset, data_size, target;
150
    uint8_t *data_ptr;
151
    uint32_t insn;
152
 
153
    data_size = (uint8_t *)data_end - (uint8_t *)data_start;
154

    
155
    if (gen_jmp) {
156
        /* generate branch to skip the data */
157
        if (data_size == 0)
158
            return gen_code_ptr;
159
        target = (long)gen_code_ptr + data_size + 4;
160
        arm_reloc_pc24((uint32_t *)gen_code_ptr, 0xeafffffe, target);
161
        gen_code_ptr += 4;
162
    }
163
   
164
    /* copy the data */
165
    data_ptr = gen_code_ptr;
166
    memcpy(gen_code_ptr, data_start, data_size);
167
    gen_code_ptr += data_size;
168
    
169
    /* patch the ldr to point to the data */
170
    for(le = ldr_start; le < ldr_end; le++) {
171
        ptr = (uint32_t *)le->ptr;
172
        offset = ((unsigned long)(le->data_ptr) - (unsigned long)data_start) + 
173
            (unsigned long)data_ptr - 
174
            (unsigned long)ptr - 8;
175
        insn = *ptr & ~(0xfff | 0x00800000);
176
        if (offset < 0) {
177
            offset = - offset;
178
        } else {
179
            insn |= 0x00800000;
180
        }
181
        if (offset > 0xfff) {
182
            fprintf(stderr, "Error ldr offset\n");
183
            abort();
184
        }
185
        insn |= offset;
186
        *ptr = insn;
187
    }
188
    return gen_code_ptr;
189
}
190

    
191
#endif /* __arm__ */
192

    
193
                       
194