X-Git-Url: https://vcs.maemo.org/git/?a=blobdiff_plain;f=dyngen.h;h=266b9e9722723cf66b4b6566ca8f36813df8d7a8;hb=f930d07eda320b221360556eaa0c695c48173567;hp=5bb170e94dac15f05fb950de7b7d40aff6a75582;hpb=fd4a43e4e28a594a20beefe78b0fe7ecd34bd981;p=qemu diff --git a/dyngen.h b/dyngen.h index 5bb170e..266b9e9 100644 --- a/dyngen.h +++ b/dyngen.h @@ -1,6 +1,6 @@ /* * dyngen helpers - * + * * Copyright (c) 2003 Fabrice Bellard * * This library is free software; you can redistribute it and/or @@ -19,28 +19,20 @@ */ int __op_param1, __op_param2, __op_param3; -int __op_gen_label1, __op_gen_label2, __op_gen_label3; -int __op_jmp0, __op_jmp1, __op_jmp2, __op_jmp3; - -#ifdef __i386__ -static inline void flush_icache_range(unsigned long start, unsigned long stop) -{ -} -#endif - -#ifdef __x86_64__ -static inline void flush_icache_range(unsigned long start, unsigned long stop) -{ -} +#if defined(__sparc__) || defined(__arm__) + void __op_gen_label1(){} + void __op_gen_label2(){} + void __op_gen_label3(){} +#else + int __op_gen_label1, __op_gen_label2, __op_gen_label3; #endif +int __op_jmp0, __op_jmp1, __op_jmp2, __op_jmp3; -#ifdef __s390__ +#if defined(__i386__) || defined(__x86_64__) || defined(__s390__) static inline void flush_icache_range(unsigned long start, unsigned long stop) { } -#endif - -#ifdef __ia64__ +#elif defined(__ia64__) static inline void flush_icache_range(unsigned long start, unsigned long stop) { while (start < stop) { @@ -49,9 +41,7 @@ static inline void flush_icache_range(unsigned long start, unsigned long stop) } asm volatile (";;sync.i;;srlz.i;;"); } -#endif - -#ifdef __powerpc__ +#elif defined(__powerpc__) #define MIN_CACHE_LINE_SIZE 8 /* conservative value */ @@ -61,7 +51,7 @@ static void inline flush_icache_range(unsigned long start, unsigned long stop) start &= ~(MIN_CACHE_LINE_SIZE - 1); stop = (stop + MIN_CACHE_LINE_SIZE - 1) & ~(MIN_CACHE_LINE_SIZE - 1); - + for (p = start; p < stop; p += MIN_CACHE_LINE_SIZE) { asm volatile ("dcbst 0,%0" : : "r"(p) : "memory"); } @@ -72,17 +62,12 @@ static void inline flush_icache_range(unsigned long start, unsigned long stop) asm volatile ("sync" : : : "memory"); asm volatile ("isync" : : : "memory"); } -#endif - -#ifdef __alpha__ +#elif defined(__alpha__) static inline void flush_icache_range(unsigned long start, unsigned long stop) { asm ("imb"); } -#endif - -#ifdef __sparc__ - +#elif defined(__sparc__) static void inline flush_icache_range(unsigned long start, unsigned long stop) { unsigned long p; @@ -93,10 +78,7 @@ static void inline flush_icache_range(unsigned long start, unsigned long stop) for (; p < stop; p += 8) __asm__ __volatile__("flush\t%0" : : "r" (p)); } - -#endif - -#ifdef __arm__ +#elif defined(__arm__) static inline void flush_icache_range(unsigned long start, unsigned long stop) { register unsigned long _beg __asm ("a1") = start; @@ -104,14 +86,22 @@ static inline void flush_icache_range(unsigned long start, unsigned long stop) register unsigned long _flg __asm ("a3") = 0; __asm __volatile__ ("swi 0x9f0002" : : "r" (_beg), "r" (_end), "r" (_flg)); } -#endif +#elif defined(__mc68000) -#ifdef __mc68000 -#include +# include static inline void flush_icache_range(unsigned long start, unsigned long stop) { cacheflush(start,FLUSH_SCOPE_LINE,FLUSH_CACHE_BOTH,stop-start+16); } +#elif defined(__mips__) + +#include +static inline void flush_icache_range(unsigned long start, unsigned long stop) +{ + _flush_cache ((void *)start, stop - start, BCACHE); +} +#else +#error unsupported CPU #endif #ifdef __alpha__ @@ -139,18 +129,16 @@ void fix_bsr(void *p, int offset) { #ifdef __arm__ -#define MAX_OP_SIZE (128 * 4) /* in bytes */ -/* max size of the code that can be generated without calling arm_flush_ldr */ -#define MAX_FRAG_SIZE (1024 * 4) -//#define MAX_FRAG_SIZE (135 * 4) /* for testing */ +#define ARM_LDR_TABLE_SIZE 1024 typedef struct LDREntry { uint8_t *ptr; uint32_t *data_ptr; + unsigned type:2; } LDREntry; static LDREntry arm_ldr_table[1024]; -static uint32_t arm_data_table[1024]; +static uint32_t arm_data_table[ARM_LDR_TABLE_SIZE]; extern char exec_loop; @@ -160,8 +148,8 @@ static inline void arm_reloc_pc24(uint32_t *ptr, uint32_t insn, int val) } static uint8_t *arm_flush_ldr(uint8_t *gen_code_ptr, - LDREntry *ldr_start, LDREntry *ldr_end, - uint32_t *data_start, uint32_t *data_end, + LDREntry *ldr_start, LDREntry *ldr_end, + uint32_t *data_start, uint32_t *data_end, int gen_jmp) { LDREntry *le; @@ -169,8 +157,9 @@ static uint8_t *arm_flush_ldr(uint8_t *gen_code_ptr, int offset, data_size, target; uint8_t *data_ptr; uint32_t insn; - - data_size = (uint8_t *)data_end - (uint8_t *)data_start; + uint32_t mask; + + data_size = (data_end - data_start) << 2; if (gen_jmp) { /* generate branch to skip the data */ @@ -180,29 +169,60 @@ static uint8_t *arm_flush_ldr(uint8_t *gen_code_ptr, arm_reloc_pc24((uint32_t *)gen_code_ptr, 0xeafffffe, target); gen_code_ptr += 4; } - + /* copy the data */ data_ptr = gen_code_ptr; memcpy(gen_code_ptr, data_start, data_size); gen_code_ptr += data_size; - + /* patch the ldr to point to the data */ for(le = ldr_start; le < ldr_end; le++) { ptr = (uint32_t *)le->ptr; - offset = ((unsigned long)(le->data_ptr) - (unsigned long)data_start) + - (unsigned long)data_ptr - + offset = ((unsigned long)(le->data_ptr) - (unsigned long)data_start) + + (unsigned long)data_ptr - (unsigned long)ptr - 8; - insn = *ptr & ~(0xfff | 0x00800000); if (offset < 0) { - offset = - offset; - } else { - insn |= 0x00800000; - } - if (offset > 0xfff) { - fprintf(stderr, "Error ldr offset\n"); + fprintf(stderr, "Negative constant pool offset\n"); abort(); } - insn |= offset; + switch (le->type) { + case 0: /* ldr */ + mask = ~0x00800fff; + if (offset >= 4096) { + fprintf(stderr, "Bad ldr offset\n"); + abort(); + } + break; + case 1: /* ldc */ + mask = ~0x008000ff; + if (offset >= 1024 ) { + fprintf(stderr, "Bad ldc offset\n"); + abort(); + } + break; + case 2: /* add */ + mask = ~0xfff; + if (offset >= 1024 ) { + fprintf(stderr, "Bad add offset\n"); + abort(); + } + break; + default: + fprintf(stderr, "Bad pc relative fixup\n"); + abort(); + } + insn = *ptr & mask; + switch (le->type) { + case 0: /* ldr */ + insn |= offset | 0x00800000; + break; + case 1: /* ldc */ + insn |= (offset >> 2) | 0x00800000; + break; + case 2: /* add */ + insn |= (offset >> 2) | 0xf00; + break; + } *ptr = insn; } return gen_code_ptr; @@ -212,7 +232,6 @@ static uint8_t *arm_flush_ldr(uint8_t *gen_code_ptr, #ifdef __ia64 - /* Patch instruction with "val" where "mask" has 1 bits. */ static inline void ia64_patch (uint64_t insn_addr, uint64_t mask, uint64_t val) { @@ -373,7 +392,8 @@ static inline void ia64_apply_fixes (uint8_t **gen_code_pp, 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, /* nop 0; brl IP */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0 }; - uint8_t *gen_code_ptr = *gen_code_pp, *plt_start, *got_start, *vp; + uint8_t *gen_code_ptr = *gen_code_pp, *plt_start, *got_start; + uint64_t *vp; struct ia64_fixup *fixup; unsigned int offset = 0; struct fdesc { @@ -410,12 +430,12 @@ static inline void ia64_apply_fixes (uint8_t **gen_code_pp, /* First, create the GOT: */ for (fixup = ltoff_fixes; fixup; fixup = fixup->next) { /* first check if we already have this value in the GOT: */ - for (vp = got_start; vp < gen_code_ptr; ++vp) - if (*(uint64_t *) vp == fixup->value) + for (vp = (uint64_t *) got_start; vp < (uint64_t *) gen_code_ptr; ++vp) + if (*vp == fixup->value) break; - if (vp == gen_code_ptr) { + if (vp == (uint64_t *) gen_code_ptr) { /* Nope, we need to put the value in the GOT: */ - *(uint64_t *) vp = fixup->value; + *vp = fixup->value; gen_code_ptr += 8; } ia64_imm22(fixup->addr, (long) vp - gp);