dyngen.h revision 9b898ee3642a830a4d4af4d0a485a49d157b5551
/*
* dyngen helpers
*
* Copyright (c) 2003 Fabrice Bellard
*
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
void __op_gen_label1(){}
void __op_gen_label2(){}
void __op_gen_label3(){}
#else
#endif
#ifdef __i386__
{
}
#endif
#ifdef __x86_64__
{
}
#endif
#ifdef __s390__
{
}
#endif
#ifdef __ia64__
{
start += 32;
}
asm volatile (";;sync.i;;srlz.i;;");
}
#endif
#ifdef __powerpc__
{
unsigned long p;
asm volatile ("dcbst 0,%0" : : "r"(p) : "memory");
}
asm volatile ("sync" : : : "memory");
asm volatile ("icbi 0,%0" : : "r"(p) : "memory");
}
asm volatile ("sync" : : : "memory");
asm volatile ("isync" : : : "memory");
}
#endif
#ifdef __alpha__
{
asm ("imb");
}
#endif
#ifdef __sparc__
{
unsigned long p;
for (; p < stop; p += 8)
}
#endif
#ifdef __arm__
{
}
#endif
#ifdef __mc68000
#include <asm/cachectl.h>
{
}
#endif
#ifdef __alpha__
register int gp asm("$29");
static inline void immediate_ldah(void *p, int val) {
*dest &= ~0xffff;
}
}
}
#endif /* __alpha__ */
#ifdef __arm__
#define ARM_LDR_TABLE_SIZE 1024
typedef struct LDREntry {
unsigned type:2;
} LDREntry;
extern char exec_loop;
{
}
int gen_jmp)
{
if (gen_jmp) {
/* generate branch to skip the data */
if (data_size == 0)
return gen_code_ptr;
gen_code_ptr += 4;
}
/* copy the data */
/* patch the ldr to point to the data */
(unsigned long)data_ptr -
(unsigned long)ptr - 8;
if (offset < 0) {
abort();
}
case 0: /* ldr */
mask = ~0x00800fff;
if (offset >= 4096) {
abort();
}
break;
case 1: /* ldc */
mask = ~0x008000ff;
if (offset >= 1024 ) {
abort();
}
break;
case 2: /* add */
mask = ~0xfff;
if (offset >= 1024 ) {
abort();
}
break;
default:
abort();
}
case 0: /* ldr */
break;
case 1: /* ldc */
break;
case 2: /* add */
break;
}
}
return gen_code_ptr;
}
#endif /* __arm__ */
#ifdef __ia64
/* Patch instruction with "val" where "mask" has 1 bits. */
{
unsigned long shift;
if (shift >= 64) {
} else {
}
}
{
0x011ffffe000UL,
}
{
/* Ignore the slot number of the relocation; GCC and Intel
toolchains differed for some time on whether IMM64 relocs are
against slot 1 (Intel) or slot 2 (GCC). */
0x01fffefe000UL,
);
}
{
/* Ignore the slot number of the relocation; GCC and Intel
toolchains differed for some time on whether IMM64 relocs are
against slot 1 (Intel) or slot 2 (GCC). */
}
{
}
/* Like ia64_imm22(), but also clear bits 20-21. For addl, this has
the effect of turning "addl rX=imm22,rY" into "addl
rX=imm22,r0". */
{
}
{
}
static inline void ia64_nop_b (void *insn)
{
}
{
}
int relaxable)
{
return 0;
}
return 1;
}
struct ia64_fixup {
struct ia64_fixup *next;
void *addr; /* address that needs to be patched */
long value;
};
do { \
} while (0)
do { \
ltoff_fixes = fixup; \
} \
} while (0)
struct ia64_fixup *ltoff_fixes,
struct ia64_fixup *plt_fixes,
int num_plts,
unsigned long *plt_target,
unsigned int *plt_offset)
{
static const uint8_t plt_bundle[] = {
0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, /* nop 0; movl r1=GP */
0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x60,
0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, /* nop 0; brl IP */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0
};
struct ia64_fixup *fixup;
unsigned int offset = 0;
struct fdesc {
long ip;
long gp;
} *fdesc;
int i;
if (plt_fixes) {
for (i = 0; i < num_plts; ++i) {
if (plt_offset[i]) {
plt_offset[i] = offset;
offset += sizeof(plt_bundle);
gen_code_ptr += sizeof(plt_bundle);
}
}
}
/* First, create the GOT: */
/* first check if we already have this value in the GOT: */
break;
if (vp == gen_code_ptr) {
/* Nope, we need to put the value in the GOT: */
gen_code_ptr += 8;
}
}
/* Keep code ptr aligned. */
if ((long) gen_code_ptr & 15)
gen_code_ptr += 8;
}
#endif