#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
int do_swap;
-void __attribute__((noreturn)) __attribute__((format (printf, 1, 2))) error(const char *fmt, ...)
+static void __attribute__((noreturn)) __attribute__((format (printf, 1, 2))) error(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
exit(1);
}
-void *load_data(int fd, long offset, unsigned int size)
+static void *load_data(int fd, long offset, unsigned int size)
{
char *data;
#endif /* CONFIG_FORMAT_MACH */
-void get_reloc_expr(char *name, int name_size, const char *sym_name)
+/* return true if the expression is a label reference */
+int get_reloc_expr(char *name, int name_size, const char *sym_name)
{
const char *p;
if (strstart(sym_name, "__op_param", &p)) {
snprintf(name, name_size, "param%s", p);
} else if (strstart(sym_name, "__op_gen_label", &p)) {
- snprintf(name, name_size, "gen_labels[param%s]", p);
+ 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)",
#endif
snprintf(name, name_size, "(long)(&%s)", sym_name);
}
+ return 0;
}
#ifdef HOST_IA64
p = (void *)(p_end - 2);
if (p == p_start)
error("empty code for %s", name);
- if (get16((uint16_t *)p) != 0x07fe && get16((uint16_t *)p) != 0x07f4)
- error("br %%r14 expected at the end of %s", name);
+ if ((get16((uint16_t *)p) & 0xfff0) != 0x07f0)
+ error("br expected at the end of %s", name);
copy_size = p - p_start;
}
#elif defined(HOST_ALPHA)
error("No save at the beginning of %s", name);
}
+#if 0
/* Skip a preceeding nop, if present. */
if (p > p_start) {
skip_insn = get32((uint32_t *)(p - 0x4));
if (skip_insn == 0x01000000)
p -= 4;
}
+#endif
copy_size = p - p_start;
}
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
!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",
}
}
+#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 */
{
#if defined(HOST_I386)
{
char relname[256];
- int type;
+ int type, is_label;
int addend;
int reloc_offset;
for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
continue;
}
- get_reloc_expr(relname, sizeof(relname), sym_name);
+ is_label = get_reloc_expr(relname, sizeof(relname), sym_name);
addend = get32((uint32_t *)(text + rel->r_offset));
#ifdef CONFIG_FORMAT_ELF
type = ELF32_R_TYPE(rel->r_info);
- switch(type) {
- case R_386_32:
- fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
- reloc_offset, relname, addend);
- break;
- case R_386_PC32:
- fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %d) + %d;\n",
- reloc_offset, relname, reloc_offset, addend);
- break;
- default:
- error("unsupported i386 relocation (%d)", type);
+ if (is_label) {
+ switch(type) {
+ case R_386_32:
+ case R_386_PC32:
+ fprintf(outfile, " tcg_out_reloc(s, gen_code_ptr + %d, %d, %s, %d);\n",
+ reloc_offset, type, relname, addend);
+ break;
+ default:
+ error("unsupported i386 relocation (%d)", type);
+ }
+ } else {
+ switch(type) {
+ case R_386_32:
+ fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
+ reloc_offset, relname, addend);
+ break;
+ case R_386_PC32:
+ fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %d) + %d;\n",
+ reloc_offset, relname, reloc_offset, addend);
+ break;
+ default:
+ error("unsupported i386 relocation (%d)", type);
+ }
}
#elif defined(CONFIG_FORMAT_COFF)
{
}
}
type = rel->r_type;
- switch(type) {
- case DIR32:
- fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
- reloc_offset, relname, addend);
- break;
- case DISP32:
- fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %d) + %d -4;\n",
- reloc_offset, relname, reloc_offset, addend);
- break;
- default:
- error("unsupported i386 relocation (%d)", type);
+ if (is_label) {
+/* TCG uses elf relocation constants */
+#define R_386_32 1
+#define R_386_PC32 2
+ switch(type) {
+ case DIR32:
+ type = R_386_32;
+ goto do_reloc;
+ case DISP32:
+ type = R_386_PC32;
+ addend -= 4;
+ do_reloc:
+ fprintf(outfile, " tcg_out_reloc(s, gen_code_ptr + %d, %d, %s, %d);\n",
+ reloc_offset, type, relname, addend);
+ break;
+ default:
+ error("unsupported i386 relocation (%d)", type);
+ }
+ } else {
+ switch(type) {
+ case DIR32:
+ fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
+ reloc_offset, relname, addend);
+ break;
+ case DISP32:
+ fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %d) + %d -4;\n",
+ reloc_offset, relname, reloc_offset, addend);
+ break;
+ default:
+ error("unsupported i386 relocation (%d)", type);
+ }
}
#else
#error unsupport object format
#elif defined(HOST_X86_64)
{
char relname[256];
- int type;
+ 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 = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name;
- get_reloc_expr(relname, sizeof(relname), sym_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;
- switch(type) {
- case R_X86_64_32:
- fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = (uint32_t)%s + %d;\n",
- reloc_offset, relname, addend);
- break;
- case R_X86_64_32S:
- fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = (int32_t)%s + %d;\n",
- reloc_offset, relname, addend);
- break;
- case R_X86_64_PC32:
- fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %d) + %d;\n",
- reloc_offset, relname, reloc_offset, addend);
- break;
- default:
- error("unsupported X86_64 relocation (%d)", type);
+ if (is_label) {
+ switch(type) {
+ case R_X86_64_32:
+ case R_X86_64_32S:
+ case R_X86_64_PC32:
+ fprintf(outfile, " tcg_out_reloc(s, gen_code_ptr + %d, %d, %s, %d);\n",
+ reloc_offset, type, relname, addend);
+ break;
+ default:
+ error("unsupported X86_64 relocation (%d)", type);
+ }
+ } else {
+ switch(type) {
+ case R_X86_64_32:
+ fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = (uint32_t)%s + %d;\n",
+ reloc_offset, relname, addend);
+ break;
+ case R_X86_64_32S:
+ fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = (int32_t)%s + %d;\n",
+ reloc_offset, relname, addend);
+ break;
+ case R_X86_64_PC32:
+ fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %d) + %d;\n",
+ reloc_offset, relname, reloc_offset, addend);
+ break;
+ default:
+ error("unsupported X86_64 relocation (%d)", type);
+ }
}
}
}
fprintf(outfile, " *(uint8_t *)(gen_code_ptr + %d) = %s + %d;\n",
reloc_offset, relname, addend);
break;
+ case R_390_PC32DBL:
+ if (ELF32_ST_TYPE(symtab[ELFW(R_SYM)(rel->r_info)].st_info) == STT_SECTION) {
+ fprintf(outfile,
+ " *(uint32_t *)(gen_code_ptr + %d) += "
+ "((long)&%s - (long)gen_code_ptr) >> 1;\n",
+ reloc_offset, name);
+ }
+ else
+ fprintf(outfile,
+ " *(uint32_t *)(gen_code_ptr + %d) = "
+ "(%s + %d - ((uint32_t)gen_code_ptr + %d)) >> 1;\n",
+ reloc_offset, relname, addend, reloc_offset);
+ break;
default:
error("unsupported s390 relocation (%d)", type);
}
}
}
}
+#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++) {
EXE_SYM *sym;
if (out_type == OUT_INDEX_OP) {
- fprintf(outfile, "DEF(end, 0, 0)\n");
- fprintf(outfile, "DEF(nop, 0, 0)\n");
- fprintf(outfile, "DEF(nop1, 1, 0)\n");
- fprintf(outfile, "DEF(nop2, 2, 0)\n");
- fprintf(outfile, "DEF(nop3, 3, 0)\n");
for(i = 0, sym = symtab; i < nb_syms; i++, sym++) {
const char *name;
name = get_sym_name(sym);
}
} else if (out_type == OUT_GEN_OP) {
/* generate gen_xxx functions */
- fprintf(outfile, "#include \"dyngen-op.h\"\n");
for(i = 0, sym = symtab; i < nb_syms; i++, sym++) {
const char *name;
name = get_sym_name(sym);
/* generate big code generation switch */
#ifdef HOST_ARM
+#error broken
/* We need to know the size of all the ops so we can figure out when
to emit constant pools. This must be consistent with opc.h. */
fprintf(outfile,
"};\n");
#endif
-fprintf(outfile,
-"int dyngen_code(uint8_t *gen_code_buf,\n"
-" uint16_t *label_offsets, uint16_t *jmp_offsets,\n"
-" const uint16_t *opc_buf, const uint32_t *opparam_buf, const long *gen_labels)\n"
-"{\n"
-" uint8_t *gen_code_ptr;\n"
-" const uint16_t *opc_ptr;\n"
-" const uint32_t *opparam_ptr;\n");
-
#ifdef HOST_ARM
+#error broken
/* Arm is tricky because it uses constant pools for loading immediate values.
We assume (and require) each function is code followed by a constant pool.
All the ops are small so this should be ok. For each op we figure
" uint8_t *arm_pool_ptr = gen_code_buf + 0x1000000;\n");
#endif
#ifdef HOST_IA64
+#error broken
{
long addend, not_first = 0;
unsigned long sym_idx;
}
#endif
-fprintf(outfile,
-"\n"
-" gen_code_ptr = gen_code_buf;\n"
-" opc_ptr = opc_buf;\n"
-" opparam_ptr = opparam_buf;\n");
-
- /* Generate prologue, if needed. */
-
-fprintf(outfile,
-" for(;;) {\n");
-
#ifdef HOST_ARM
+#error broken
/* Generate constant pool if needed */
fprintf(outfile,
" if (gen_code_ptr + arm_opc_size[*opc_ptr] >= arm_pool_ptr) {\n"
" }\n");
#endif
-fprintf(outfile,
-" switch(*opc_ptr++) {\n");
-
for(i = 0, sym = symtab; i < nb_syms; i++, sym++) {
const char *name;
name = get_sym_name(sym);
gen_code(name, sym->st_value, sym->st_size, outfile, 1);
}
}
-
-fprintf(outfile,
-" case INDEX_op_nop:\n"
-" break;\n"
-" case INDEX_op_nop1:\n"
-" opparam_ptr++;\n"
-" break;\n"
-" case INDEX_op_nop2:\n"
-" opparam_ptr += 2;\n"
-" break;\n"
-" case INDEX_op_nop3:\n"
-" opparam_ptr += 3;\n"
-" break;\n"
-" default:\n"
-" goto the_end;\n"
-" }\n");
-
-
-fprintf(outfile,
-" }\n"
-" the_end:\n"
-);
-#ifdef HOST_IA64
- fprintf(outfile,
- " {\n"
- " extern char code_gen_buffer[];\n"
- " ia64_apply_fixes(&gen_code_ptr, ltoff_fixes, "
- "(uint64_t) code_gen_buffer + 2*(1<<20), plt_fixes,\n\t\t\t"
- "sizeof(plt_target)/sizeof(plt_target[0]),\n\t\t\t"
- "plt_target, plt_offset);\n }\n");
-#endif
-
-/* generate some code patching */
-#ifdef HOST_ARM
-fprintf(outfile,
-"if (arm_data_ptr != arm_data_table + ARM_LDR_TABLE_SIZE)\n"
-" gen_code_ptr = arm_flush_ldr(gen_code_ptr, arm_ldr_table, "
-"arm_ldr_ptr, arm_data_ptr, arm_data_table + ARM_LDR_TABLE_SIZE, 0);\n");
-#endif
- /* flush instruction cache */
- fprintf(outfile, "flush_icache_range((unsigned long)gen_code_buf, (unsigned long)gen_code_ptr);\n");
-
- fprintf(outfile, "return gen_code_ptr - gen_code_buf;\n");
- fprintf(outfile, "}\n\n");
-
}
return 0;