Commit 38e584a07279fffcfbfcafb207ce842edd093033
1 parent
313aa567
m68k host port (Richard Zidlicky)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@357 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
8 changed files
with
293 additions
and
2 deletions
Makefile.target
| ... | ... | @@ -79,6 +79,11 @@ OP_CFLAGS=$(CFLAGS) -mno-sched-prolog |
| 79 | 79 | LDFLAGS+=-Wl,-T,$(SRC_PATH)/arm.ld |
| 80 | 80 | endif |
| 81 | 81 | |
| 82 | +ifeq ($(ARCH),m68k) | |
| 83 | +OP_CFLAGS=$(CFLAGS) -fomit-frame-pointer | |
| 84 | +LDFLAGS+=-Wl,-T,m68k.ld | |
| 85 | +endif | |
| 86 | + | |
| 82 | 87 | ifeq ($(HAVE_GCC3_OPTIONS),yes) |
| 83 | 88 | # very important to generate a return at the end of every operation |
| 84 | 89 | OP_CFLAGS+=-fno-reorder-blocks -fno-optimize-sibling-calls | ... | ... |
configure
| ... | ... | @@ -56,6 +56,9 @@ case "$cpu" in |
| 56 | 56 | ia64) |
| 57 | 57 | cpu="ia64" |
| 58 | 58 | ;; |
| 59 | + m68k) | |
| 60 | + cpu="m68k" | |
| 61 | + ;; | |
| 59 | 62 | *) |
| 60 | 63 | cpu="unknown" |
| 61 | 64 | ;; |
| ... | ... | @@ -163,7 +166,7 @@ fi |
| 163 | 166 | else |
| 164 | 167 | |
| 165 | 168 | # if cross compiling, cannot launch a program, so make a static guess |
| 166 | -if test "$cpu" = "powerpc" -o "$cpu" = "mips" -o "$cpu" = "s390" -o "$cpu" = "sparc" -o "$cpu" = "sparc64"; then | |
| 169 | +if test "$cpu" = "powerpc" -o "$cpu" = "mips" -o "$cpu" = "s390" -o "$cpu" = "sparc" -o "$cpu" = "sparc64" -o "$cpu" = "m68k"; then | |
| 167 | 170 | bigendian="yes" |
| 168 | 171 | fi |
| 169 | 172 | |
| ... | ... | @@ -265,6 +268,9 @@ elif test "$cpu" = "sparc64" ; then |
| 265 | 268 | elif test "$cpu" = "ia64" ; then |
| 266 | 269 | echo "ARCH=ia64" >> $config_mak |
| 267 | 270 | echo "#define HOST_IA64 1" >> $config_h |
| 271 | +elif test "$cpu" = "m68k" ; then | |
| 272 | + echo "ARCH=m68k" >> config.mak | |
| 273 | + echo "#define HOST_M68K 1" >> $TMPH | |
| 268 | 274 | else |
| 269 | 275 | echo "Unsupported CPU" |
| 270 | 276 | exit 1 | ... | ... |
cpu-exec.c
| ... | ... | @@ -642,6 +642,23 @@ int cpu_signal_handler(int host_signum, struct siginfo *info, |
| 642 | 642 | &uc->uc_sigmask); |
| 643 | 643 | } |
| 644 | 644 | |
| 645 | +#elif defined(__mc68000) | |
| 646 | + | |
| 647 | +int cpu_signal_handler(int host_signum, struct siginfo *info, | |
| 648 | + void *puc) | |
| 649 | +{ | |
| 650 | + struct ucontext *uc = puc; | |
| 651 | + unsigned long pc; | |
| 652 | + int is_write; | |
| 653 | + | |
| 654 | + pc = uc->uc_mcontext.gregs[16]; | |
| 655 | + /* XXX: compute is_write */ | |
| 656 | + is_write = 0; | |
| 657 | + return handle_cpu_signal(pc, (unsigned long)info->si_addr, | |
| 658 | + is_write, | |
| 659 | + &uc->uc_sigmask); | |
| 660 | +} | |
| 661 | + | |
| 645 | 662 | #else |
| 646 | 663 | |
| 647 | 664 | #error host CPU specific signal handler needed | ... | ... |
dyngen-exec.h
| ... | ... | @@ -109,6 +109,13 @@ extern int printf(const char *, ...); |
| 109 | 109 | #define AREG5 "$13" |
| 110 | 110 | #define AREG6 "$14" |
| 111 | 111 | #endif |
| 112 | +#ifdef __mc68000 | |
| 113 | +#define AREG0 "%a5" | |
| 114 | +#define AREG1 "%a4" | |
| 115 | +#define AREG2 "%d7" | |
| 116 | +#define AREG3 "%d6" | |
| 117 | +#define AREG4 "%d5" | |
| 118 | +#endif | |
| 112 | 119 | #ifdef __ia64__ |
| 113 | 120 | #define AREG0 "r27" |
| 114 | 121 | #define AREG1 "r24" |
| ... | ... | @@ -178,4 +185,6 @@ extern int __op_jmp0, __op_jmp1; |
| 178 | 185 | #ifdef __arm__ |
| 179 | 186 | #define EXIT_TB() asm volatile ("b exec_loop") |
| 180 | 187 | #endif |
| 181 | - | |
| 188 | +#ifdef __mc68000 | |
| 189 | +#define EXIT_TB() asm volatile ("rts") | |
| 190 | +#endif | ... | ... |
dyngen.c
| ... | ... | @@ -86,6 +86,13 @@ |
| 86 | 86 | #define elf_check_arch(x) ((x) == EM_ARM) |
| 87 | 87 | #define ELF_USES_RELOC |
| 88 | 88 | |
| 89 | +#elif defined(HOST_M68K) | |
| 90 | + | |
| 91 | +#define ELF_CLASS ELFCLASS32 | |
| 92 | +#define ELF_ARCH EM_68K | |
| 93 | +#define elf_check_arch(x) ((x) == EM_68K) | |
| 94 | +#define ELF_USES_RELOCA | |
| 95 | + | |
| 89 | 96 | #else |
| 90 | 97 | #error unsupported CPU - please update the code |
| 91 | 98 | #endif |
| ... | ... | @@ -575,6 +582,21 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, |
| 575 | 582 | relocs, nb_relocs); |
| 576 | 583 | break; |
| 577 | 584 | #endif |
| 585 | + case EM_68K: | |
| 586 | + { | |
| 587 | + uint8_t *p; | |
| 588 | + p = (void *)(p_end - 2); | |
| 589 | + if (p == p_start) | |
| 590 | + error("empty code for %s", name); | |
| 591 | + // remove NOP's, probably added for alignment | |
| 592 | + while ((get16((uint16_t *)p) == 0x4e71) && | |
| 593 | + (p>p_start)) | |
| 594 | + p -= 2; | |
| 595 | + if (get16((uint16_t *)p) != 0x4e75) | |
| 596 | + error("rts expected at the end of %s", name); | |
| 597 | + copy_size = p - p_start; | |
| 598 | + } | |
| 599 | + break; | |
| 578 | 600 | default: |
| 579 | 601 | error("unknown ELF architecture"); |
| 580 | 602 | } |
| ... | ... | @@ -1062,6 +1084,41 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, |
| 1062 | 1084 | } |
| 1063 | 1085 | } |
| 1064 | 1086 | } |
| 1087 | +#elif defined(HOST_M68K) | |
| 1088 | + { | |
| 1089 | + char name[256]; | |
| 1090 | + int type; | |
| 1091 | + int addend; | |
| 1092 | + Elf32_Sym *sym; | |
| 1093 | + for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) { | |
| 1094 | + if (rel->r_offset >= start_offset && | |
| 1095 | + rel->r_offset < start_offset + copy_size) { | |
| 1096 | + sym = &(symtab[ELFW(R_SYM)(rel->r_info)]); | |
| 1097 | + sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name; | |
| 1098 | + if (strstart(sym_name, "__op_param", &p)) { | |
| 1099 | + snprintf(name, sizeof(name), "param%s", p); | |
| 1100 | + } else { | |
| 1101 | + snprintf(name, sizeof(name), "(long)(&%s)", sym_name); | |
| 1102 | + } | |
| 1103 | + type = ELF32_R_TYPE(rel->r_info); | |
| 1104 | + addend = get32((uint32_t *)(text + rel->r_offset)) + rel->r_addend; | |
| 1105 | + switch(type) { | |
| 1106 | + case R_68K_32: | |
| 1107 | + fprintf(outfile, " /* R_68K_32 RELOC, offset %x */\n", rel->r_offset) ; | |
| 1108 | + fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %#x;\n", | |
| 1109 | + rel->r_offset - start_offset, name, addend ); | |
| 1110 | + break; | |
| 1111 | + case R_68K_PC32: | |
| 1112 | + fprintf(outfile, " /* R_68K_PC32 RELOC, offset %x */\n", rel->r_offset); | |
| 1113 | + fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %#x) + %#x;\n", | |
| 1114 | + rel->r_offset - start_offset, name, rel->r_offset - start_offset, /*sym->st_value+*/ addend); | |
| 1115 | + break; | |
| 1116 | + default: | |
| 1117 | + error("unsupported m68k relocation (%d)", type); | |
| 1118 | + } | |
| 1119 | + } | |
| 1120 | + } | |
| 1121 | + } | |
| 1065 | 1122 | #else |
| 1066 | 1123 | #error unsupported CPU |
| 1067 | 1124 | #endif | ... | ... |
dyngen.h
| ... | ... | @@ -94,6 +94,14 @@ static inline void flush_icache_range(unsigned long start, unsigned long stop) |
| 94 | 94 | } |
| 95 | 95 | #endif |
| 96 | 96 | |
| 97 | +#ifdef __mc68000 | |
| 98 | +#include <asm/cachectl.h> | |
| 99 | +static inline void flush_icache_range(unsigned long start, unsigned long stop) | |
| 100 | +{ | |
| 101 | + cacheflush(start,FLUSH_SCOPE_LINE,FLUSH_CACHE_BOTH,stop-start+16); | |
| 102 | +} | |
| 103 | +#endif | |
| 104 | + | |
| 97 | 105 | #ifdef __alpha__ |
| 98 | 106 | |
| 99 | 107 | register int gp asm("$29"); | ... | ... |
exec.h
| ... | ... | @@ -348,6 +348,18 @@ static inline int testandset (int *spinlock) |
| 348 | 348 | } |
| 349 | 349 | #endif |
| 350 | 350 | |
| 351 | +#ifdef __mc68000 | |
| 352 | +static inline int testandset (int *p) | |
| 353 | +{ | |
| 354 | + char ret; | |
| 355 | + __asm__ __volatile__("tas %1; sne %0" | |
| 356 | + : "=r" (ret) | |
| 357 | + : "m" (p) | |
| 358 | + : "cc","memory"); | |
| 359 | + return ret == 0; | |
| 360 | +} | |
| 361 | +#endif | |
| 362 | + | |
| 351 | 363 | typedef int spinlock_t; |
| 352 | 364 | |
| 353 | 365 | #define SPIN_LOCK_UNLOCKED 0 | ... | ... |
m68k.ld
0 โ 100644
| 1 | +/* Script for -z combreloc: combine and sort reloc sections */ | |
| 2 | +OUTPUT_FORMAT("elf32-m68k", "elf32-m68k", | |
| 3 | + "elf32-m68k") | |
| 4 | +OUTPUT_ARCH(m68k) | |
| 5 | +ENTRY(_start) | |
| 6 | +SEARCH_DIR("/usr/local/m68k-linux/lib"); | |
| 7 | +/* Do we need any of these for elf? | |
| 8 | + __DYNAMIC = 0; */ | |
| 9 | +SECTIONS | |
| 10 | +{ | |
| 11 | + /* Read-only sections, merged into text segment: */ | |
| 12 | + . = 0x60000000 + SIZEOF_HEADERS; | |
| 13 | + .interp : { *(.interp) } | |
| 14 | + .hash : { *(.hash) } | |
| 15 | + .dynsym : { *(.dynsym) } | |
| 16 | + .dynstr : { *(.dynstr) } | |
| 17 | + .gnu.version : { *(.gnu.version) } | |
| 18 | + .gnu.version_d : { *(.gnu.version_d) } | |
| 19 | + .gnu.version_r : { *(.gnu.version_r) } | |
| 20 | + .rel.dyn : | |
| 21 | + { | |
| 22 | + *(.rel.init) | |
| 23 | + *(.rel.text .rel.text.* .rel.gnu.linkonce.t.*) | |
| 24 | + *(.rel.fini) | |
| 25 | + *(.rel.rodata .rel.rodata.* .rel.gnu.linkonce.r.*) | |
| 26 | + *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*) | |
| 27 | + *(.rel.tdata .rel.tdata.* .rel.gnu.linkonce.td.*) | |
| 28 | + *(.rel.tbss .rel.tbss.* .rel.gnu.linkonce.tb.*) | |
| 29 | + *(.rel.ctors) | |
| 30 | + *(.rel.dtors) | |
| 31 | + *(.rel.got) | |
| 32 | + *(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*) | |
| 33 | + } | |
| 34 | + .rela.dyn : | |
| 35 | + { | |
| 36 | + *(.rela.init) | |
| 37 | + *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*) | |
| 38 | + *(.rela.fini) | |
| 39 | + *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*) | |
| 40 | + *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*) | |
| 41 | + *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*) | |
| 42 | + *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*) | |
| 43 | + *(.rela.ctors) | |
| 44 | + *(.rela.dtors) | |
| 45 | + *(.rela.got) | |
| 46 | + *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*) | |
| 47 | + } | |
| 48 | + .rel.plt : { *(.rel.plt) } | |
| 49 | + .rela.plt : { *(.rela.plt) } | |
| 50 | + .init : | |
| 51 | + { | |
| 52 | + KEEP (*(.init)) | |
| 53 | + } =0x4e754e75 | |
| 54 | + .plt : { *(.plt) } | |
| 55 | + .text : | |
| 56 | + { | |
| 57 | + *(.text .stub .text.* .gnu.linkonce.t.*) | |
| 58 | + /* .gnu.warning sections are handled specially by elf32.em. */ | |
| 59 | + *(.gnu.warning) | |
| 60 | + } =0x4e754e75 | |
| 61 | + .fini : | |
| 62 | + { | |
| 63 | + KEEP (*(.fini)) | |
| 64 | + } =0x4e754e75 | |
| 65 | + PROVIDE (__etext = .); | |
| 66 | + PROVIDE (_etext = .); | |
| 67 | + PROVIDE (etext = .); | |
| 68 | + .rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) } | |
| 69 | + .rodata1 : { *(.rodata1) } | |
| 70 | + .eh_frame_hdr : { *(.eh_frame_hdr) } | |
| 71 | + /* Adjust the address for the data segment. We want to adjust up to | |
| 72 | + the same address within the page on the next page up. */ | |
| 73 | + . = ALIGN(0x2000) + (. & (0x2000 - 1)); | |
| 74 | + /* Ensure the __preinit_array_start label is properly aligned. We | |
| 75 | + could instead move the label definition inside the section, but | |
| 76 | + the linker would then create the section even if it turns out to | |
| 77 | + be empty, which isn't pretty. */ | |
| 78 | + . = ALIGN(32 / 8); | |
| 79 | + PROVIDE (__preinit_array_start = .); | |
| 80 | + .preinit_array : { *(.preinit_array) } | |
| 81 | + PROVIDE (__preinit_array_end = .); | |
| 82 | + PROVIDE (__init_array_start = .); | |
| 83 | + .init_array : { *(.init_array) } | |
| 84 | + PROVIDE (__init_array_end = .); | |
| 85 | + PROVIDE (__fini_array_start = .); | |
| 86 | + .fini_array : { *(.fini_array) } | |
| 87 | + PROVIDE (__fini_array_end = .); | |
| 88 | + .data : | |
| 89 | + { | |
| 90 | + *(.data .data.* .gnu.linkonce.d.*) | |
| 91 | + SORT(CONSTRUCTORS) | |
| 92 | + } | |
| 93 | + .data1 : { *(.data1) } | |
| 94 | + .tdata : { *(.tdata .tdata.* .gnu.linkonce.td.*) } | |
| 95 | + .tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) } | |
| 96 | + .eh_frame : { KEEP (*(.eh_frame)) } | |
| 97 | + .gcc_except_table : { *(.gcc_except_table) } | |
| 98 | + .dynamic : { *(.dynamic) } | |
| 99 | + .ctors : | |
| 100 | + { | |
| 101 | + /* gcc uses crtbegin.o to find the start of | |
| 102 | + the constructors, so we make sure it is | |
| 103 | + first. Because this is a wildcard, it | |
| 104 | + doesn't matter if the user does not | |
| 105 | + actually link against crtbegin.o; the | |
| 106 | + linker won't look for a file to match a | |
| 107 | + wildcard. The wildcard also means that it | |
| 108 | + doesn't matter which directory crtbegin.o | |
| 109 | + is in. */ | |
| 110 | + KEEP (*crtbegin.o(.ctors)) | |
| 111 | + /* We don't want to include the .ctor section from | |
| 112 | + from the crtend.o file until after the sorted ctors. | |
| 113 | + The .ctor section from the crtend file contains the | |
| 114 | + end of ctors marker and it must be last */ | |
| 115 | + KEEP (*(EXCLUDE_FILE (*crtend.o ) .ctors)) | |
| 116 | + KEEP (*(SORT(.ctors.*))) | |
| 117 | + KEEP (*(.ctors)) | |
| 118 | + } | |
| 119 | + .dtors : | |
| 120 | + { | |
| 121 | + KEEP (*crtbegin.o(.dtors)) | |
| 122 | + KEEP (*(EXCLUDE_FILE (*crtend.o ) .dtors)) | |
| 123 | + KEEP (*(SORT(.dtors.*))) | |
| 124 | + KEEP (*(.dtors)) | |
| 125 | + } | |
| 126 | + .jcr : { KEEP (*(.jcr)) } | |
| 127 | + .got : { *(.got.plt) *(.got) } | |
| 128 | + _edata = .; | |
| 129 | + PROVIDE (edata = .); | |
| 130 | + __bss_start = .; | |
| 131 | + .bss : | |
| 132 | + { | |
| 133 | + *(.dynbss) | |
| 134 | + *(.bss .bss.* .gnu.linkonce.b.*) | |
| 135 | + *(COMMON) | |
| 136 | + /* Align here to ensure that the .bss section occupies space up to | |
| 137 | + _end. Align after .bss to ensure correct alignment even if the | |
| 138 | + .bss section disappears because there are no input sections. */ | |
| 139 | + . = ALIGN(32 / 8); | |
| 140 | + } | |
| 141 | + . = ALIGN(32 / 8); | |
| 142 | + _end = .; | |
| 143 | + PROVIDE (end = .); | |
| 144 | + /* Stabs debugging sections. */ | |
| 145 | + .stab 0 : { *(.stab) } | |
| 146 | + .stabstr 0 : { *(.stabstr) } | |
| 147 | + .stab.excl 0 : { *(.stab.excl) } | |
| 148 | + .stab.exclstr 0 : { *(.stab.exclstr) } | |
| 149 | + .stab.index 0 : { *(.stab.index) } | |
| 150 | + .stab.indexstr 0 : { *(.stab.indexstr) } | |
| 151 | + .comment 0 : { *(.comment) } | |
| 152 | + /* DWARF debug sections. | |
| 153 | + Symbols in the DWARF debugging sections are relative to the beginning | |
| 154 | + of the section so we begin them at 0. */ | |
| 155 | + /* DWARF 1 */ | |
| 156 | + .debug 0 : { *(.debug) } | |
| 157 | + .line 0 : { *(.line) } | |
| 158 | + /* GNU DWARF 1 extensions */ | |
| 159 | + .debug_srcinfo 0 : { *(.debug_srcinfo) } | |
| 160 | + .debug_sfnames 0 : { *(.debug_sfnames) } | |
| 161 | + /* DWARF 1.1 and DWARF 2 */ | |
| 162 | + .debug_aranges 0 : { *(.debug_aranges) } | |
| 163 | + .debug_pubnames 0 : { *(.debug_pubnames) } | |
| 164 | + /* DWARF 2 */ | |
| 165 | + .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } | |
| 166 | + .debug_abbrev 0 : { *(.debug_abbrev) } | |
| 167 | + .debug_line 0 : { *(.debug_line) } | |
| 168 | + .debug_frame 0 : { *(.debug_frame) } | |
| 169 | + .debug_str 0 : { *(.debug_str) } | |
| 170 | + .debug_loc 0 : { *(.debug_loc) } | |
| 171 | + .debug_macinfo 0 : { *(.debug_macinfo) } | |
| 172 | + /* SGI/MIPS DWARF 2 extensions */ | |
| 173 | + .debug_weaknames 0 : { *(.debug_weaknames) } | |
| 174 | + .debug_funcnames 0 : { *(.debug_funcnames) } | |
| 175 | + .debug_typenames 0 : { *(.debug_typenames) } | |
| 176 | + .debug_varnames 0 : { *(.debug_varnames) } | |
| 177 | +} | ... | ... |