mirror of
https://github.com/izzy2lost/xemu.git
synced 2026-07-06 00:20:22 -07:00
HPPA (PA-RISC) host support
(Stuart Brady) git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4199 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
@@ -128,6 +128,11 @@ ifeq ($(ARCH),alpha)
|
||||
CFLAGS+=-msmall-data
|
||||
endif
|
||||
|
||||
ifeq ($(ARCH),hppa)
|
||||
OP_CFLAGS=-O1 -fno-delayed-branch
|
||||
BASE_LDFLAGS+=-Wl,-T,$(SRC_PATH)/$(ARCH).ld
|
||||
endif
|
||||
|
||||
ifeq ($(ARCH),ia64)
|
||||
CFLAGS+=-mno-sdata
|
||||
OP_CFLAGS+=-mno-sdata
|
||||
@@ -267,6 +272,9 @@ endif
|
||||
ifeq ($(findstring sh4, $(TARGET_ARCH) $(ARCH)),sh4)
|
||||
LIBOBJS+=sh4-dis.o
|
||||
endif
|
||||
ifeq ($(findstring hppa, $(TARGET_BASE_ARCH) $(ARCH)),hppa)
|
||||
LIBOBJS+=hppa-dis.o
|
||||
endif
|
||||
ifeq ($(findstring s390, $(TARGET_ARCH) $(ARCH)),s390)
|
||||
LIBOBJS+=s390-dis.o
|
||||
endif
|
||||
|
||||
@@ -50,6 +50,9 @@ case "$cpu" in
|
||||
cris)
|
||||
cpu="cris"
|
||||
;;
|
||||
parisc|parisc64)
|
||||
cpu="hppa"
|
||||
;;
|
||||
ia64)
|
||||
cpu="ia64"
|
||||
;;
|
||||
@@ -576,6 +579,7 @@ else
|
||||
|
||||
# if cross compiling, cannot launch a program, so make a static guess
|
||||
if test "$cpu" = "armv4b" \
|
||||
-o "$cpu" = "hppa" \
|
||||
-o "$cpu" = "m68k" \
|
||||
-o "$cpu" = "mips" \
|
||||
-o "$cpu" = "mips64" \
|
||||
@@ -865,6 +869,9 @@ elif test "$cpu" = "armv4l" ; then
|
||||
elif test "$cpu" = "cris" ; then
|
||||
echo "ARCH=cris" >> $config_mak
|
||||
echo "#define HOST_CRIS 1" >> $config_h
|
||||
elif test "$cpu" = "hppa" ; then
|
||||
echo "ARCH=hppa" >> $config_mak
|
||||
echo "#define HOST_HPPA 1" >> $config_h
|
||||
elif test "$cpu" = "ia64" ; then
|
||||
echo "ARCH=ia64" >> $config_mak
|
||||
echo "#define HOST_IA64 1" >> $config_h
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
#ifndef CPU_ALL_H
|
||||
#define CPU_ALL_H
|
||||
|
||||
#if defined(__arm__) || defined(__sparc__) || defined(__mips__)
|
||||
#if defined(__arm__) || defined(__sparc__) || defined(__mips__) || defined(__hppa__)
|
||||
#define WORDS_ALIGNED
|
||||
#endif
|
||||
|
||||
@@ -952,6 +952,15 @@ static inline int64_t cpu_get_real_ticks(void)
|
||||
return val;
|
||||
}
|
||||
|
||||
#elif defined(__hppa__)
|
||||
|
||||
static inline int64_t cpu_get_real_ticks(void)
|
||||
{
|
||||
int val;
|
||||
asm volatile ("mfctl %%cr16, %0" : "=r"(val));
|
||||
return val;
|
||||
}
|
||||
|
||||
#elif defined(__ia64)
|
||||
|
||||
static inline int64_t cpu_get_real_ticks(void)
|
||||
|
||||
+29
@@ -657,6 +657,17 @@ int cpu_exec(CPUState *env1)
|
||||
"o0", "o1", "o2", "o3", "o4", "o5",
|
||||
"l0", "l1", "l2", "l3", "l4", "l5",
|
||||
"l6", "l7");
|
||||
#elif defined(__hppa__)
|
||||
asm volatile ("ble 0(%%sr4,%1)\n"
|
||||
"copy %%r31,%%r18\n"
|
||||
"copy %%r28,%0\n"
|
||||
: "=r" (T0)
|
||||
: "r" (gen_func)
|
||||
: "r1", "r2", "r3", "r4", "r5", "r6", "r7",
|
||||
"r8", "r9", "r10", "r11", "r12", "r13",
|
||||
"r18", "r19", "r20", "r21", "r22", "r23",
|
||||
"r24", "r25", "r26", "r27", "r28", "r29",
|
||||
"r30", "r31");
|
||||
#elif defined(__arm__)
|
||||
asm volatile ("mov pc, %0\n\t"
|
||||
".global exec_loop\n\t"
|
||||
@@ -1488,6 +1499,24 @@ int cpu_signal_handler(int host_signum, void *pinfo,
|
||||
is_write, &uc->uc_sigmask, puc);
|
||||
}
|
||||
|
||||
#elif defined(__hppa__)
|
||||
|
||||
int cpu_signal_handler(int host_signum, void *pinfo,
|
||||
void *puc)
|
||||
{
|
||||
struct siginfo *info = pinfo;
|
||||
struct ucontext *uc = puc;
|
||||
unsigned long pc;
|
||||
int is_write;
|
||||
|
||||
pc = uc->uc_mcontext.sc_iaoq[0];
|
||||
/* FIXME: compute is_write */
|
||||
is_write = 0;
|
||||
return handle_cpu_signal(pc, (unsigned long)info->si_addr,
|
||||
is_write,
|
||||
&uc->uc_sigmask, puc);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#error host CPU specific signal handler needed
|
||||
|
||||
@@ -157,6 +157,10 @@ enum bfd_architecture
|
||||
#define bfd_mach_ppc_7400 7400
|
||||
bfd_arch_rs6000, /* IBM RS/6000 */
|
||||
bfd_arch_hppa, /* HP PA RISC */
|
||||
#define bfd_mach_hppa10 10
|
||||
#define bfd_mach_hppa11 11
|
||||
#define bfd_mach_hppa20 20
|
||||
#define bfd_mach_hppa20w 25
|
||||
bfd_arch_d10v, /* Mitsubishi D10V */
|
||||
bfd_arch_z8k, /* Zilog Z8000 */
|
||||
#define bfd_mach_z8001 1
|
||||
|
||||
@@ -279,6 +279,8 @@ void disas(FILE *out, void *code, unsigned long size)
|
||||
print_insn = print_insn_m68k;
|
||||
#elif defined(__s390__)
|
||||
print_insn = print_insn_s390;
|
||||
#elif defined(__hppa__)
|
||||
print_insn = print_insn_hppa;
|
||||
#else
|
||||
fprintf(out, "0x%lx: Asm output not supported on this arch\n",
|
||||
(long) code);
|
||||
|
||||
@@ -124,6 +124,11 @@ extern int printf(const char *, ...);
|
||||
#define AREG1 "r4"
|
||||
#define AREG2 "r5"
|
||||
#define AREG3 "r6"
|
||||
#elif defined(__hppa__)
|
||||
#define AREG0 "r17"
|
||||
#define AREG1 "r14"
|
||||
#define AREG2 "r15"
|
||||
#define AREG3 "r16"
|
||||
#elif defined(__mips__)
|
||||
#define AREG0 "fp"
|
||||
#define AREG1 "s0"
|
||||
@@ -279,6 +284,8 @@ extern int __op_jmp0, __op_jmp1, __op_jmp2, __op_jmp3;
|
||||
#elif defined(__mips__)
|
||||
#define EXIT_TB() asm volatile ("jr $ra")
|
||||
#define GOTO_LABEL_PARAM(n) asm volatile (".set noat; la $1, " ASM_NAME(__op_gen_label) #n "; jr $1; .set at")
|
||||
#elif defined(__hppa__)
|
||||
#define GOTO_LABEL_PARAM(n) asm volatile ("b,n " ASM_NAME(__op_gen_label) #n)
|
||||
#else
|
||||
#error unsupported CPU
|
||||
#endif
|
||||
|
||||
@@ -117,6 +117,13 @@
|
||||
#define elf_check_arch(x) ((x) == EM_68K)
|
||||
#define ELF_USES_RELOCA
|
||||
|
||||
#elif defined(HOST_HPPA)
|
||||
|
||||
#define ELF_CLASS ELFCLASS32
|
||||
#define ELF_ARCH EM_PARISC
|
||||
#define elf_check_arch(x) ((x) == EM_PARISC)
|
||||
#define ELF_USES_RELOCA
|
||||
|
||||
#elif defined(HOST_MIPS)
|
||||
|
||||
#define ELF_CLASS ELFCLASS32
|
||||
@@ -1223,7 +1230,7 @@ int get_reloc_expr(char *name, int name_size, const char *sym_name)
|
||||
snprintf(name, name_size, "param%s", p);
|
||||
return 1;
|
||||
} else {
|
||||
#ifdef HOST_SPARC
|
||||
#if defined(HOST_SPARC) || defined(HOST_HPPA)
|
||||
if (sym_name[0] == '.')
|
||||
snprintf(name, name_size,
|
||||
"(long)(&__dot_%s)",
|
||||
@@ -1661,6 +1668,43 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
|
||||
error("rts expected at the end of %s", name);
|
||||
copy_size = p - p_start;
|
||||
}
|
||||
#elif defined(HOST_HPPA)
|
||||
{
|
||||
uint8_t *p;
|
||||
p = p_start;
|
||||
while (p < p_end) {
|
||||
uint32_t insn = get32((uint32_t *)p);
|
||||
if (insn == 0x6bc23fd9 || /* stw rp,-14(sp) */
|
||||
insn == 0x08030241 || /* copy r3,r1 */
|
||||
insn == 0x081e0243 || /* copy sp,r3 */
|
||||
(insn & 0xffffc000) == 0x37de0000 || /* ldo x(sp),sp */
|
||||
(insn & 0xffffc000) == 0x6fc10000) /* stwm r1,x(sp) */
|
||||
p += 4;
|
||||
else
|
||||
break;
|
||||
}
|
||||
start_offset += p - p_start;
|
||||
p_start = p;
|
||||
p = p_end - 4;
|
||||
|
||||
while (p > p_start) {
|
||||
uint32_t insn = get32((uint32_t *)p);
|
||||
if ((insn & 0xffffc000) == 0x347e0000 || /* ldo x(r3),sp */
|
||||
(insn & 0xffe0c000) == 0x4fc00000 || /* ldwm x(sp),rx */
|
||||
(insn & 0xffffc000) == 0x37de0000 || /* ldo x(sp),sp */
|
||||
insn == 0x48623fd9 || /* ldw -14(r3),rp */
|
||||
insn == 0xe840c000 || /* bv r0(rp) */
|
||||
insn == 0xe840c002) /* bv,n r0(rp) */
|
||||
p -= 4;
|
||||
else
|
||||
break;
|
||||
}
|
||||
p += 4;
|
||||
if (p <= p_start)
|
||||
error("empty code for %s", name);
|
||||
|
||||
copy_size = p - p_start;
|
||||
}
|
||||
#elif defined(HOST_MIPS) || defined(HOST_MIPS64)
|
||||
{
|
||||
#define INSN_RETURN 0x03e00008
|
||||
@@ -1746,7 +1790,7 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
|
||||
!strstart(sym_name, "__op_param", NULL) &&
|
||||
!strstart(sym_name, "__op_jmp", NULL) &&
|
||||
!strstart(sym_name, "__op_gen_label", NULL)) {
|
||||
#if defined(HOST_SPARC)
|
||||
#if defined(HOST_SPARC) || defined(HOST_HPPA)
|
||||
if (sym_name[0] == '.') {
|
||||
fprintf(outfile,
|
||||
"extern char __dot_%s __asm__(\"%s\");\n",
|
||||
@@ -1774,8 +1818,13 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef __hppa__
|
||||
fprintf(outfile, " memcpy(gen_code_ptr, (void *)((char *)__canonicalize_funcptr_for_compare(%s)+%d), %d);\n",
|
||||
name, (int)(start_offset - offset), copy_size);
|
||||
#else
|
||||
fprintf(outfile, " memcpy(gen_code_ptr, (void *)((char *)&%s+%d), %d);\n",
|
||||
name, (int)(start_offset - offset), copy_size);
|
||||
#endif
|
||||
|
||||
/* emit code offset information */
|
||||
{
|
||||
@@ -2581,6 +2630,82 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
|
||||
}
|
||||
}
|
||||
}
|
||||
#elif defined(HOST_HPPA)
|
||||
{
|
||||
char relname[256];
|
||||
int type, is_label;
|
||||
int addend;
|
||||
int reloc_offset;
|
||||
for (i = 0, rel = relocs; i < nb_relocs; i++, rel++) {
|
||||
if (rel->r_offset >= start_offset &&
|
||||
rel->r_offset < start_offset + copy_size) {
|
||||
sym_name = get_rel_sym_name(rel);
|
||||
sym_name = strtab + symtab[ELF32_R_SYM(rel->r_info)].st_name;
|
||||
is_label = get_reloc_expr(relname, sizeof(relname), sym_name);
|
||||
type = ELF32_R_TYPE(rel->r_info);
|
||||
addend = rel->r_addend;
|
||||
reloc_offset = rel->r_offset - start_offset;
|
||||
|
||||
if (is_label) {
|
||||
switch (type) {
|
||||
case R_PARISC_PCREL17F:
|
||||
fprintf(outfile,
|
||||
" tcg_out_reloc(s, gen_code_ptr + %d, %d, %s, %d);\n",
|
||||
reloc_offset, type, relname, addend);
|
||||
break;
|
||||
default:
|
||||
error("unsupported hppa label relocation (%d)", type);
|
||||
}
|
||||
} else {
|
||||
switch (type) {
|
||||
case R_PARISC_DIR21L:
|
||||
fprintf(outfile,
|
||||
" hppa_patch21l((uint32_t *)(gen_code_ptr + %d), %s, %d);\n",
|
||||
reloc_offset, relname, addend);
|
||||
break;
|
||||
case R_PARISC_DIR14R:
|
||||
fprintf(outfile,
|
||||
" hppa_patch14r((uint32_t *)(gen_code_ptr + %d), %s, %d);\n",
|
||||
reloc_offset, relname, addend);
|
||||
break;
|
||||
case R_PARISC_PCREL17F:
|
||||
if (strstart(sym_name, "__op_gen_label", NULL)) {
|
||||
fprintf(outfile,
|
||||
" hppa_patch17f((uint32_t *)(gen_code_ptr + %d), %s, %d);\n",
|
||||
reloc_offset, relname, addend);
|
||||
} else {
|
||||
fprintf(outfile,
|
||||
" HPPA_RECORD_BRANCH(hppa_stubs, (uint32_t *)(gen_code_ptr + %d), %s);\n",
|
||||
reloc_offset, relname);
|
||||
}
|
||||
break;
|
||||
case R_PARISC_DPREL21L:
|
||||
if (strstart(sym_name, "__op_param", &p))
|
||||
fprintf(outfile,
|
||||
" hppa_load_imm21l((uint32_t *)(gen_code_ptr + %d), param%s, %d);\n",
|
||||
reloc_offset, p, addend);
|
||||
else
|
||||
fprintf(outfile,
|
||||
" hppa_patch21l_dprel((uint32_t *)(gen_code_ptr + %d), %s, %d);\n",
|
||||
reloc_offset, relname, addend);
|
||||
break;
|
||||
case R_PARISC_DPREL14R:
|
||||
if (strstart(sym_name, "__op_param", &p))
|
||||
fprintf(outfile,
|
||||
" hppa_load_imm14r((uint32_t *)(gen_code_ptr + %d), param%s, %d);\n",
|
||||
reloc_offset, p, addend);
|
||||
else
|
||||
fprintf(outfile,
|
||||
" hppa_patch14r_dprel((uint32_t *)(gen_code_ptr + %d), %s, %d);\n",
|
||||
reloc_offset, relname, addend);
|
||||
break;
|
||||
default:
|
||||
error("unsupported hppa relocation (%d)", type);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#elif defined(HOST_MIPS) || defined(HOST_MIPS64)
|
||||
{
|
||||
for (i = 0, rel = relocs; i < nb_relocs; i++, rel++) {
|
||||
|
||||
+2834
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,214 @@
|
||||
/* Default linker script, for normal executables */
|
||||
OUTPUT_FORMAT("elf32-hppa-linux", "elf32-hppa-linux",
|
||||
"elf32-hppa-linux")
|
||||
OUTPUT_ARCH(hppa:hppa1.1)
|
||||
ENTRY(_start)
|
||||
SEARCH_DIR("/usr/hppa-linux-gnu/lib"); SEARCH_DIR("/usr/local/lib"); SEARCH_DIR("/lib"); SEARCH_DIR("/usr/lib");
|
||||
SECTIONS
|
||||
{
|
||||
/* Read-only sections, merged into text segment: */
|
||||
PROVIDE (__executable_start = 0x60000000); . = 0x60000000 + SIZEOF_HEADERS;
|
||||
.interp : { *(.interp) }
|
||||
.hash : { *(.hash) }
|
||||
.dynsym : { *(.dynsym) }
|
||||
.dynstr : { *(.dynstr) }
|
||||
.gnu.version : { *(.gnu.version) }
|
||||
.gnu.version_d : { *(.gnu.version_d) }
|
||||
.gnu.version_r : { *(.gnu.version_r) }
|
||||
.rel.init : { *(.rel.init) }
|
||||
.rela.init : { *(.rela.init) }
|
||||
.rel.text : { *(.rel.text .rel.text.* .rel.gnu.linkonce.t.*) }
|
||||
.rela.text : { *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*) }
|
||||
.rel.fini : { *(.rel.fini) }
|
||||
.rela.fini : { *(.rela.fini) }
|
||||
.rel.rodata : { *(.rel.rodata .rel.rodata.* .rel.gnu.linkonce.r.*) }
|
||||
.rela.rodata : { *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*) }
|
||||
.rel.data.rel.ro : { *(.rel.data.rel.ro* .rel.gnu.linkonce.d.rel.ro.*) }
|
||||
.rela.data.rel.ro : { *(.rela.data.rel.ro* .rela.gnu.linkonce.d.rel.ro.*) }
|
||||
.rel.data : { *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*) }
|
||||
.rela.data : { *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*) }
|
||||
.rel.tdata : { *(.rel.tdata .rel.tdata.* .rel.gnu.linkonce.td.*) }
|
||||
.rela.tdata : { *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*) }
|
||||
.rel.tbss : { *(.rel.tbss .rel.tbss.* .rel.gnu.linkonce.tb.*) }
|
||||
.rela.tbss : { *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*) }
|
||||
.rel.ctors : { *(.rel.ctors) }
|
||||
.rela.ctors : { *(.rela.ctors) }
|
||||
.rel.dtors : { *(.rel.dtors) }
|
||||
.rela.dtors : { *(.rela.dtors) }
|
||||
.rel.got : { *(.rel.got) }
|
||||
.rela.got : { *(.rela.got) }
|
||||
.rel.sdata : { *(.rel.sdata .rel.sdata.* .rel.gnu.linkonce.s.*) }
|
||||
.rela.sdata : { *(.rela.sdata .rela.sdata.* .rela.gnu.linkonce.s.*) }
|
||||
.rel.sbss : { *(.rel.sbss .rel.sbss.* .rel.gnu.linkonce.sb.*) }
|
||||
.rela.sbss : { *(.rela.sbss .rela.sbss.* .rela.gnu.linkonce.sb.*) }
|
||||
.rel.sdata2 : { *(.rel.sdata2 .rel.sdata2.* .rel.gnu.linkonce.s2.*) }
|
||||
.rela.sdata2 : { *(.rela.sdata2 .rela.sdata2.* .rela.gnu.linkonce.s2.*) }
|
||||
.rel.sbss2 : { *(.rel.sbss2 .rel.sbss2.* .rel.gnu.linkonce.sb2.*) }
|
||||
.rela.sbss2 : { *(.rela.sbss2 .rela.sbss2.* .rela.gnu.linkonce.sb2.*) }
|
||||
.rel.bss : { *(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*) }
|
||||
.rela.bss : { *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*) }
|
||||
.rel.plt : { *(.rel.plt) }
|
||||
.rela.plt : { *(.rela.plt) }
|
||||
.init :
|
||||
{
|
||||
KEEP (*(.init))
|
||||
} =0x08000240
|
||||
.text :
|
||||
{
|
||||
*(.text .stub .text.* .gnu.linkonce.t.*)
|
||||
KEEP (*(.text.*personality*))
|
||||
/* .gnu.warning sections are handled specially by elf32.em. */
|
||||
*(.gnu.warning)
|
||||
} =0x08000240
|
||||
.fini :
|
||||
{
|
||||
KEEP (*(.fini))
|
||||
} =0x08000240
|
||||
PROVIDE (__etext = .);
|
||||
PROVIDE (_etext = .);
|
||||
PROVIDE (etext = .);
|
||||
.rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) }
|
||||
.rodata1 : { *(.rodata1) }
|
||||
.sdata2 :
|
||||
{
|
||||
*(.sdata2 .sdata2.* .gnu.linkonce.s2.*)
|
||||
}
|
||||
.sbss2 : { *(.sbss2 .sbss2.* .gnu.linkonce.sb2.*) }
|
||||
.PARISC.unwind : { *(.PARISC.unwind) }
|
||||
.eh_frame_hdr : { *(.eh_frame_hdr) }
|
||||
.eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) }
|
||||
.gcc_except_table : ONLY_IF_RO { *(.gcc_except_table .gcc_except_table.*) }
|
||||
/* Adjust the address for the data segment. We want to adjust up to
|
||||
the same address within the page on the next page up. */
|
||||
. = ALIGN(0x10000) + (. & (0x10000 - 1));
|
||||
/* Exception handling */
|
||||
.eh_frame : ONLY_IF_RW { KEEP (*(.eh_frame)) }
|
||||
.gcc_except_table : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) }
|
||||
/* Thread Local Storage sections */
|
||||
.tdata : { *(.tdata .tdata.* .gnu.linkonce.td.*) }
|
||||
.tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) }
|
||||
.preinit_array :
|
||||
{
|
||||
PROVIDE_HIDDEN (__preinit_array_start = .);
|
||||
KEEP (*(.preinit_array))
|
||||
PROVIDE_HIDDEN (__preinit_array_end = .);
|
||||
}
|
||||
.init_array :
|
||||
{
|
||||
PROVIDE_HIDDEN (__init_array_start = .);
|
||||
KEEP (*(SORT(.init_array.*)))
|
||||
KEEP (*(.init_array))
|
||||
PROVIDE_HIDDEN (__init_array_end = .);
|
||||
}
|
||||
.fini_array :
|
||||
{
|
||||
PROVIDE_HIDDEN (__fini_array_start = .);
|
||||
KEEP (*(.fini_array))
|
||||
KEEP (*(SORT(.fini_array.*)))
|
||||
PROVIDE_HIDDEN (__fini_array_end = .);
|
||||
}
|
||||
.ctors :
|
||||
{
|
||||
/* gcc uses crtbegin.o to find the start of
|
||||
the constructors, so we make sure it is
|
||||
first. Because this is a wildcard, it
|
||||
doesn't matter if the user does not
|
||||
actually link against crtbegin.o; the
|
||||
linker won't look for a file to match a
|
||||
wildcard. The wildcard also means that it
|
||||
doesn't matter which directory crtbegin.o
|
||||
is in. */
|
||||
KEEP (*crtbegin*.o(.ctors))
|
||||
/* We don't want to include the .ctor section from
|
||||
the crtend.o file until after the sorted ctors.
|
||||
The .ctor section from the crtend file contains the
|
||||
end of ctors marker and it must be last */
|
||||
KEEP (*(EXCLUDE_FILE (*crtend*.o ) .ctors))
|
||||
KEEP (*(SORT(.ctors.*)))
|
||||
KEEP (*(.ctors))
|
||||
}
|
||||
.dtors :
|
||||
{
|
||||
KEEP (*crtbegin*.o(.dtors))
|
||||
KEEP (*(EXCLUDE_FILE (*crtend*.o ) .dtors))
|
||||
KEEP (*(SORT(.dtors.*)))
|
||||
KEEP (*(.dtors))
|
||||
}
|
||||
.jcr : { KEEP (*(.jcr)) }
|
||||
.data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro* .gnu.linkonce.d.rel.ro.*) }
|
||||
.dynamic : { *(.dynamic) }
|
||||
.data :
|
||||
{
|
||||
PROVIDE ($global$ = .);
|
||||
*(.data .data.* .gnu.linkonce.d.*)
|
||||
KEEP (*(.gnu.linkonce.d.*personality*))
|
||||
SORT(CONSTRUCTORS)
|
||||
}
|
||||
.data1 : { *(.data1) }
|
||||
.plt : { *(.plt) }
|
||||
.got : { *(.got.plt) *(.got) }
|
||||
/* We want the small data sections together, so single-instruction offsets
|
||||
can access them all, and initialized data all before uninitialized, so
|
||||
we can shorten the on-disk segment size. */
|
||||
.sdata :
|
||||
{
|
||||
*(.sdata .sdata.* .gnu.linkonce.s.*)
|
||||
}
|
||||
_edata = .; PROVIDE (edata = .);
|
||||
__bss_start = .;
|
||||
.sbss :
|
||||
{
|
||||
*(.dynsbss)
|
||||
*(.sbss .sbss.* .gnu.linkonce.sb.*)
|
||||
*(.scommon)
|
||||
}
|
||||
.bss :
|
||||
{
|
||||
*(.dynbss)
|
||||
*(.bss .bss.* .gnu.linkonce.b.*)
|
||||
*(COMMON)
|
||||
/* Align here to ensure that the .bss section occupies space up to
|
||||
_end. Align after .bss to ensure correct alignment even if the
|
||||
.bss section disappears because there are no input sections.
|
||||
FIXME: Why do we need it? When there is no .bss section, we don't
|
||||
pad the .data section. */
|
||||
. = ALIGN(. != 0 ? 32 / 8 : 1);
|
||||
}
|
||||
. = ALIGN(32 / 8);
|
||||
. = ALIGN(32 / 8);
|
||||
_end = .; PROVIDE (end = .);
|
||||
/* Stabs debugging sections. */
|
||||
.stab 0 : { *(.stab) }
|
||||
.stabstr 0 : { *(.stabstr) }
|
||||
.stab.excl 0 : { *(.stab.excl) }
|
||||
.stab.exclstr 0 : { *(.stab.exclstr) }
|
||||
.stab.index 0 : { *(.stab.index) }
|
||||
.stab.indexstr 0 : { *(.stab.indexstr) }
|
||||
.comment 0 : { *(.comment) }
|
||||
/* DWARF debug sections.
|
||||
Symbols in the DWARF debugging sections are relative to the beginning
|
||||
of the section so we begin them at 0. */
|
||||
/* DWARF 1 */
|
||||
.debug 0 : { *(.debug) }
|
||||
.line 0 : { *(.line) }
|
||||
/* GNU DWARF 1 extensions */
|
||||
.debug_srcinfo 0 : { *(.debug_srcinfo) }
|
||||
.debug_sfnames 0 : { *(.debug_sfnames) }
|
||||
/* DWARF 1.1 and DWARF 2 */
|
||||
.debug_aranges 0 : { *(.debug_aranges) }
|
||||
.debug_pubnames 0 : { *(.debug_pubnames) }
|
||||
/* DWARF 2 */
|
||||
.debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
|
||||
.debug_abbrev 0 : { *(.debug_abbrev) }
|
||||
.debug_line 0 : { *(.debug_line) }
|
||||
.debug_frame 0 : { *(.debug_frame) }
|
||||
.debug_str 0 : { *(.debug_str) }
|
||||
.debug_loc 0 : { *(.debug_loc) }
|
||||
.debug_macinfo 0 : { *(.debug_macinfo) }
|
||||
/* SGI/MIPS DWARF 2 extensions */
|
||||
.debug_weaknames 0 : { *(.debug_weaknames) }
|
||||
.debug_funcnames 0 : { *(.debug_funcnames) }
|
||||
.debug_typenames 0 : { *(.debug_typenames) }
|
||||
.debug_varnames 0 : { *(.debug_varnames) }
|
||||
/DISCARD/ : { *(.note.GNU-stack) }
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,204 @@
|
||||
/*
|
||||
* Tiny Code Generator for QEMU
|
||||
*
|
||||
* Copyright (c) 2008 Fabrice Bellard
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#define TCG_TARGET_HPPA 1
|
||||
|
||||
#if defined(_PA_RISC1_1)
|
||||
#define TCG_TARGET_REG_BITS 32
|
||||
#else
|
||||
#error unsupported
|
||||
#endif
|
||||
|
||||
#define TCG_TARGET_WORDS_BIGENDIAN
|
||||
|
||||
#define TCG_TARGET_NB_REGS 32
|
||||
|
||||
enum {
|
||||
TCG_REG_R0 = 0,
|
||||
TCG_REG_R1,
|
||||
TCG_REG_RP,
|
||||
TCG_REG_R3,
|
||||
TCG_REG_R4,
|
||||
TCG_REG_R5,
|
||||
TCG_REG_R6,
|
||||
TCG_REG_R7,
|
||||
TCG_REG_R8,
|
||||
TCG_REG_R9,
|
||||
TCG_REG_R10,
|
||||
TCG_REG_R11,
|
||||
TCG_REG_R12,
|
||||
TCG_REG_R13,
|
||||
TCG_REG_R14,
|
||||
TCG_REG_R15,
|
||||
TCG_REG_R16,
|
||||
TCG_REG_R17,
|
||||
TCG_REG_R18,
|
||||
TCG_REG_R19,
|
||||
TCG_REG_R20,
|
||||
TCG_REG_R21,
|
||||
TCG_REG_R22,
|
||||
TCG_REG_R23,
|
||||
TCG_REG_R24,
|
||||
TCG_REG_R25,
|
||||
TCG_REG_R26,
|
||||
TCG_REG_DP,
|
||||
TCG_REG_RET0,
|
||||
TCG_REG_RET1,
|
||||
TCG_REG_SP,
|
||||
TCG_REG_R31,
|
||||
};
|
||||
|
||||
/* used for function call generation */
|
||||
#define TCG_REG_CALL_STACK TCG_REG_SP
|
||||
#define TCG_TARGET_STACK_ALIGN 16
|
||||
#define TCG_TARGET_STACK_GROWSUP
|
||||
|
||||
/* optional instructions */
|
||||
//#define TCG_TARGET_HAS_ext8s_i32
|
||||
//#define TCG_TARGET_HAS_ext16s_i32
|
||||
//#define TCG_TARGET_HAS_bswap16_i32
|
||||
//#define TCG_TARGET_HAS_bswap_i32
|
||||
|
||||
/* Note: must be synced with dyngen-exec.h */
|
||||
#define TCG_AREG0 TCG_REG_R17
|
||||
#define TCG_AREG1 TCG_REG_R14
|
||||
#define TCG_AREG2 TCG_REG_R15
|
||||
#define TCG_AREG3 TCG_REG_R16
|
||||
|
||||
static inline void flush_icache_range(unsigned long start, unsigned long stop)
|
||||
{
|
||||
start &= ~31;
|
||||
while (start <= stop)
|
||||
{
|
||||
asm volatile ("fdc 0(%0)\n"
|
||||
"sync\n"
|
||||
"fic 0(%%sr4, %0)\n"
|
||||
"sync\n"
|
||||
: : "r"(start) : "memory");
|
||||
start += 32;
|
||||
}
|
||||
}
|
||||
|
||||
/* supplied by libgcc */
|
||||
extern void *__canonicalize_funcptr_for_compare(void *);
|
||||
|
||||
/* Field selection types defined by hppa */
|
||||
#define rnd(x) (((x)+0x1000)&~0x1fff)
|
||||
/* lsel: select left 21 bits */
|
||||
#define lsel(v,a) (((v)+(a))>>11)
|
||||
/* rsel: select right 11 bits */
|
||||
#define rsel(v,a) (((v)+(a))&0x7ff)
|
||||
/* lrsel with rounding of addend to nearest 8k */
|
||||
#define lrsel(v,a) (((v)+rnd(a))>>11)
|
||||
/* rrsel with rounding of addend to nearest 8k */
|
||||
#define rrsel(v,a) ((((v)+rnd(a))&0x7ff)+((a)-rnd(a)))
|
||||
|
||||
#define mask(x,sz) ((x) & ~((1<<(sz))-1))
|
||||
|
||||
static inline int reassemble_12(int as12)
|
||||
{
|
||||
return (((as12 & 0x800) >> 11) |
|
||||
((as12 & 0x400) >> 8) |
|
||||
((as12 & 0x3ff) << 3));
|
||||
}
|
||||
|
||||
static inline int reassemble_14(int as14)
|
||||
{
|
||||
return (((as14 & 0x1fff) << 1) |
|
||||
((as14 & 0x2000) >> 13));
|
||||
}
|
||||
|
||||
static inline int reassemble_17(int as17)
|
||||
{
|
||||
return (((as17 & 0x10000) >> 16) |
|
||||
((as17 & 0x0f800) << 5) |
|
||||
((as17 & 0x00400) >> 8) |
|
||||
((as17 & 0x003ff) << 3));
|
||||
}
|
||||
|
||||
static inline int reassemble_21(int as21)
|
||||
{
|
||||
return (((as21 & 0x100000) >> 20) |
|
||||
((as21 & 0x0ffe00) >> 8) |
|
||||
((as21 & 0x000180) << 7) |
|
||||
((as21 & 0x00007c) << 14) |
|
||||
((as21 & 0x000003) << 12));
|
||||
}
|
||||
|
||||
static inline void hppa_patch21l(uint32_t *insn, int val, int addend)
|
||||
{
|
||||
val = lrsel(val, addend);
|
||||
*insn = mask(*insn, 21) | reassemble_21(val);
|
||||
}
|
||||
|
||||
static inline void hppa_patch14r(uint32_t *insn, int val, int addend)
|
||||
{
|
||||
val = rrsel(val, addend);
|
||||
*insn = mask(*insn, 14) | reassemble_14(val);
|
||||
}
|
||||
|
||||
static inline void hppa_patch17r(uint32_t *insn, int val, int addend)
|
||||
{
|
||||
val = rrsel(val, addend);
|
||||
*insn = (*insn & ~0x1f1ffd) | reassemble_17(val);
|
||||
}
|
||||
|
||||
|
||||
static inline void hppa_patch21l_dprel(uint32_t *insn, int val, int addend)
|
||||
{
|
||||
register unsigned int dp asm("r27");
|
||||
hppa_patch21l(insn, val - dp, addend);
|
||||
}
|
||||
|
||||
static inline void hppa_patch14r_dprel(uint32_t *insn, int val, int addend)
|
||||
{
|
||||
register unsigned int dp asm("r27");
|
||||
hppa_patch14r(insn, val - dp, addend);
|
||||
}
|
||||
|
||||
static inline void hppa_patch17f(uint32_t *insn, int val, int addend)
|
||||
{
|
||||
int dot = (int)insn & ~0x3;
|
||||
int v = ((val + addend) - dot - 8) / 4;
|
||||
if (v > (1 << 16) || v < -(1 << 16)) {
|
||||
printf("cannot fit branch to offset %d [%08x->%08x]\n", v, dot, val);
|
||||
abort();
|
||||
}
|
||||
*insn = (*insn & ~0x1f1ffd) | reassemble_17(v);
|
||||
}
|
||||
|
||||
static inline void hppa_load_imm21l(uint32_t *insn, int val, int addend)
|
||||
{
|
||||
/* Transform addil L'sym(%dp) to ldil L'val, %r1 */
|
||||
*insn = 0x20200000 | reassemble_21(lrsel(val, 0));
|
||||
}
|
||||
|
||||
static inline void hppa_load_imm14r(uint32_t *insn, int val, int addend)
|
||||
{
|
||||
/* Transform ldw R'sym(%r1), %rN to ldo R'sym(%r1), %rN */
|
||||
hppa_patch14r(insn, val, addend);
|
||||
/* HACK */
|
||||
if (addend == 0)
|
||||
*insn = (*insn & ~0xfc000000) | (0x0d << 26);
|
||||
}
|
||||
@@ -47,8 +47,9 @@ const int tcg_target_call_iarg_regs[3] = { TCG_REG_EAX, TCG_REG_EDX, TCG_REG_ECX
|
||||
const int tcg_target_call_oarg_regs[2] = { TCG_REG_EAX, TCG_REG_EDX };
|
||||
|
||||
static void patch_reloc(uint8_t *code_ptr, int type,
|
||||
tcg_target_long value)
|
||||
tcg_target_long value, tcg_target_long addend)
|
||||
{
|
||||
value += addend;
|
||||
switch(type) {
|
||||
case R_386_32:
|
||||
*(uint32_t *)code_ptr = value;
|
||||
|
||||
@@ -88,8 +88,9 @@ static const int tcg_target_call_oarg_regs[2] = {
|
||||
};
|
||||
|
||||
static void patch_reloc(uint8_t *code_ptr, int type,
|
||||
tcg_target_long value)
|
||||
tcg_target_long value, tcg_target_long addend)
|
||||
{
|
||||
value += addend;
|
||||
switch (type) {
|
||||
case R_SPARC_32:
|
||||
if (value != (uint32_t)value)
|
||||
|
||||
@@ -465,10 +465,55 @@ static inline void ia64_apply_fixes (uint8_t **gen_code_pp,
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_NO_DYNGEN_OP
|
||||
|
||||
#if defined __hppa__
|
||||
struct hppa_branch_stub {
|
||||
uint32_t *location;
|
||||
long target;
|
||||
struct hppa_branch_stub *next;
|
||||
};
|
||||
|
||||
#define HPPA_RECORD_BRANCH(LIST, LOC, TARGET) \
|
||||
do { \
|
||||
struct hppa_branch_stub *stub = alloca(sizeof(struct hppa_branch_stub)); \
|
||||
stub->location = LOC; \
|
||||
stub->target = TARGET; \
|
||||
stub->next = LIST; \
|
||||
LIST = stub; \
|
||||
} while (0)
|
||||
|
||||
static inline void hppa_process_stubs(struct hppa_branch_stub *stub,
|
||||
uint8_t **gen_code_pp)
|
||||
{
|
||||
uint32_t *s = (uint32_t *)*gen_code_pp;
|
||||
uint32_t *p = s + 1;
|
||||
|
||||
if (!stub) return;
|
||||
|
||||
for (; stub != NULL; stub = stub->next) {
|
||||
unsigned long l = (unsigned long)p;
|
||||
/* stub:
|
||||
* ldil L'target, %r1
|
||||
* be,n R'target(%sr4,%r1)
|
||||
*/
|
||||
*p++ = 0x20200000 | reassemble_21(lrsel(stub->target, 0));
|
||||
*p++ = 0xe0202002 | (reassemble_17(rrsel(stub->target, 0) >> 2));
|
||||
hppa_patch17f(stub->location, l, 0);
|
||||
}
|
||||
/* b,l,n stub,%r0 */
|
||||
*s = 0xe8000002 | reassemble_17((p - s) - 2);
|
||||
*gen_code_pp = (uint8_t *)p;
|
||||
}
|
||||
#endif /* __hppa__ */
|
||||
|
||||
const TCGArg *dyngen_op(TCGContext *s, int opc, const TCGArg *opparam_ptr)
|
||||
{
|
||||
uint8_t *gen_code_ptr;
|
||||
|
||||
#ifdef __hppa__
|
||||
struct hppa_branch_stub *hppa_stubs = NULL;
|
||||
#endif
|
||||
|
||||
gen_code_ptr = s->code_ptr;
|
||||
switch(opc) {
|
||||
|
||||
@@ -478,6 +523,11 @@ const TCGArg *dyngen_op(TCGContext *s, int opc, const TCGArg *opparam_ptr)
|
||||
default:
|
||||
tcg_abort();
|
||||
}
|
||||
|
||||
#ifdef __hppa__
|
||||
hppa_process_stubs(hppa_stubs, &gen_code_ptr);
|
||||
#endif
|
||||
|
||||
s->code_ptr = gen_code_ptr;
|
||||
return opparam_ptr;
|
||||
}
|
||||
|
||||
@@ -53,7 +53,7 @@
|
||||
|
||||
|
||||
static void patch_reloc(uint8_t *code_ptr, int type,
|
||||
tcg_target_long value);
|
||||
tcg_target_long value, tcg_target_long addend);
|
||||
|
||||
TCGOpDef tcg_op_defs[] = {
|
||||
#define DEF(s, n, copy_size) { #s, 0, 0, n, n, 0, copy_size },
|
||||
@@ -100,7 +100,7 @@ void tcg_out_reloc(TCGContext *s, uint8_t *code_ptr, int type,
|
||||
/* FIXME: This may break relocations on RISC targets that
|
||||
modify instruction fields in place. The caller may not have
|
||||
written the initial value. */
|
||||
patch_reloc(code_ptr, type, l->u.value + addend);
|
||||
patch_reloc(code_ptr, type, l->u.value, addend);
|
||||
} else {
|
||||
/* add a new relocation entry */
|
||||
r = tcg_malloc(sizeof(TCGRelocation));
|
||||
@@ -123,7 +123,7 @@ static void tcg_out_label(TCGContext *s, int label_index,
|
||||
tcg_abort();
|
||||
r = l->u.first_reloc;
|
||||
while (r != NULL) {
|
||||
patch_reloc(r->ptr, r->type, value + r->addend);
|
||||
patch_reloc(r->ptr, r->type, value, r->addend);
|
||||
r = r->next;
|
||||
}
|
||||
l->has_value = 1;
|
||||
@@ -1442,7 +1442,7 @@ static int tcg_reg_alloc_call(TCGContext *s, const TCGOpDef *def,
|
||||
int nb_iargs, nb_oargs, flags, nb_regs, i, reg, nb_params;
|
||||
TCGArg arg, func_arg;
|
||||
TCGTemp *ts;
|
||||
tcg_target_long stack_offset, call_stack_size;
|
||||
tcg_target_long stack_offset, call_stack_size, func_addr;
|
||||
int const_func_arg;
|
||||
TCGRegSet allocated_regs;
|
||||
const TCGArgConstraint *arg_ct;
|
||||
@@ -1464,7 +1464,11 @@ static int tcg_reg_alloc_call(TCGContext *s, const TCGOpDef *def,
|
||||
call_stack_size = (nb_params - nb_regs) * sizeof(tcg_target_long);
|
||||
call_stack_size = (call_stack_size + TCG_TARGET_STACK_ALIGN - 1) &
|
||||
~(TCG_TARGET_STACK_ALIGN - 1);
|
||||
#ifdef TCG_TARGET_STACK_GROWSUP
|
||||
tcg_out_addi(s, TCG_REG_CALL_STACK, call_stack_size);
|
||||
#else
|
||||
tcg_out_addi(s, TCG_REG_CALL_STACK, -call_stack_size);
|
||||
#endif
|
||||
|
||||
stack_offset = 0;
|
||||
for(i = nb_regs; i < nb_params; i++) {
|
||||
@@ -1487,7 +1491,11 @@ static int tcg_reg_alloc_call(TCGContext *s, const TCGOpDef *def,
|
||||
} else {
|
||||
tcg_abort();
|
||||
}
|
||||
#ifdef TCG_TARGET_STACK_GROWSUP
|
||||
stack_offset -= sizeof(tcg_target_long);
|
||||
#else
|
||||
stack_offset += sizeof(tcg_target_long);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* assign input registers */
|
||||
@@ -1516,6 +1524,10 @@ static int tcg_reg_alloc_call(TCGContext *s, const TCGOpDef *def,
|
||||
func_arg = args[nb_oargs + nb_iargs - 1];
|
||||
arg_ct = &def->args_ct[0];
|
||||
ts = &s->temps[func_arg];
|
||||
func_addr = ts->val;
|
||||
#ifdef HOST_HPPA
|
||||
func_addr = (tcg_target_long)__canonicalize_funcptr_for_compare((void *)func_addr);
|
||||
#endif
|
||||
const_func_arg = 0;
|
||||
if (ts->val_type == TEMP_VAL_MEM) {
|
||||
reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
|
||||
@@ -1529,12 +1541,12 @@ static int tcg_reg_alloc_call(TCGContext *s, const TCGOpDef *def,
|
||||
}
|
||||
func_arg = reg;
|
||||
} else if (ts->val_type == TEMP_VAL_CONST) {
|
||||
if (tcg_target_const_match(ts->val, arg_ct)) {
|
||||
if (tcg_target_const_match(func_addr, arg_ct)) {
|
||||
const_func_arg = 1;
|
||||
func_arg = ts->val;
|
||||
func_arg = func_addr;
|
||||
} else {
|
||||
reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
|
||||
tcg_out_movi(s, ts->type, reg, ts->val);
|
||||
tcg_out_movi(s, ts->type, reg, func_addr);
|
||||
func_arg = reg;
|
||||
}
|
||||
} else {
|
||||
@@ -1574,7 +1586,11 @@ static int tcg_reg_alloc_call(TCGContext *s, const TCGOpDef *def,
|
||||
|
||||
tcg_out_op(s, opc, &func_arg, &const_func_arg);
|
||||
|
||||
#ifdef TCG_TARGET_STACK_GROWSUP
|
||||
tcg_out_addi(s, TCG_REG_CALL_STACK, -call_stack_size);
|
||||
#else
|
||||
tcg_out_addi(s, TCG_REG_CALL_STACK, call_stack_size);
|
||||
#endif
|
||||
|
||||
/* assign output registers and emit moves if needed */
|
||||
for(i = 0; i < nb_oargs; i++) {
|
||||
|
||||
@@ -74,8 +74,9 @@ const int tcg_target_call_oarg_regs[2] = {
|
||||
};
|
||||
|
||||
static void patch_reloc(uint8_t *code_ptr, int type,
|
||||
tcg_target_long value)
|
||||
tcg_target_long value, tcg_target_long addend)
|
||||
{
|
||||
value += addend;
|
||||
switch(type) {
|
||||
case R_X86_64_32:
|
||||
if (value != (uint32_t)value)
|
||||
|
||||
Reference in New Issue
Block a user