提交 f54b3f92 编写于 作者: A aurel32

HPPA (PA-RISC) host support

(Stuart Brady)


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4199 c046a42c-6fe2-441c-8c8c-71466251a162
上级 339dea27
......@@ -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)
......
......@@ -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++) {
......
此差异已折叠。
/* 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) }
}
此差异已折叠。
/*
* 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)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册