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,6 +79,11 @@ OP_CFLAGS=$(CFLAGS) -mno-sched-prolog | ||
79 | LDFLAGS+=-Wl,-T,$(SRC_PATH)/arm.ld | 79 | LDFLAGS+=-Wl,-T,$(SRC_PATH)/arm.ld |
80 | endif | 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 | ifeq ($(HAVE_GCC3_OPTIONS),yes) | 87 | ifeq ($(HAVE_GCC3_OPTIONS),yes) |
83 | # very important to generate a return at the end of every operation | 88 | # very important to generate a return at the end of every operation |
84 | OP_CFLAGS+=-fno-reorder-blocks -fno-optimize-sibling-calls | 89 | OP_CFLAGS+=-fno-reorder-blocks -fno-optimize-sibling-calls |
configure
@@ -56,6 +56,9 @@ case "$cpu" in | @@ -56,6 +56,9 @@ case "$cpu" in | ||
56 | ia64) | 56 | ia64) |
57 | cpu="ia64" | 57 | cpu="ia64" |
58 | ;; | 58 | ;; |
59 | + m68k) | ||
60 | + cpu="m68k" | ||
61 | + ;; | ||
59 | *) | 62 | *) |
60 | cpu="unknown" | 63 | cpu="unknown" |
61 | ;; | 64 | ;; |
@@ -163,7 +166,7 @@ fi | @@ -163,7 +166,7 @@ fi | ||
163 | else | 166 | else |
164 | 167 | ||
165 | # if cross compiling, cannot launch a program, so make a static guess | 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 | bigendian="yes" | 170 | bigendian="yes" |
168 | fi | 171 | fi |
169 | 172 | ||
@@ -265,6 +268,9 @@ elif test "$cpu" = "sparc64" ; then | @@ -265,6 +268,9 @@ elif test "$cpu" = "sparc64" ; then | ||
265 | elif test "$cpu" = "ia64" ; then | 268 | elif test "$cpu" = "ia64" ; then |
266 | echo "ARCH=ia64" >> $config_mak | 269 | echo "ARCH=ia64" >> $config_mak |
267 | echo "#define HOST_IA64 1" >> $config_h | 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 | else | 274 | else |
269 | echo "Unsupported CPU" | 275 | echo "Unsupported CPU" |
270 | exit 1 | 276 | exit 1 |
cpu-exec.c
@@ -642,6 +642,23 @@ int cpu_signal_handler(int host_signum, struct siginfo *info, | @@ -642,6 +642,23 @@ int cpu_signal_handler(int host_signum, struct siginfo *info, | ||
642 | &uc->uc_sigmask); | 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 | #else | 662 | #else |
646 | 663 | ||
647 | #error host CPU specific signal handler needed | 664 | #error host CPU specific signal handler needed |
dyngen-exec.h
@@ -109,6 +109,13 @@ extern int printf(const char *, ...); | @@ -109,6 +109,13 @@ extern int printf(const char *, ...); | ||
109 | #define AREG5 "$13" | 109 | #define AREG5 "$13" |
110 | #define AREG6 "$14" | 110 | #define AREG6 "$14" |
111 | #endif | 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 | #ifdef __ia64__ | 119 | #ifdef __ia64__ |
113 | #define AREG0 "r27" | 120 | #define AREG0 "r27" |
114 | #define AREG1 "r24" | 121 | #define AREG1 "r24" |
@@ -178,4 +185,6 @@ extern int __op_jmp0, __op_jmp1; | @@ -178,4 +185,6 @@ extern int __op_jmp0, __op_jmp1; | ||
178 | #ifdef __arm__ | 185 | #ifdef __arm__ |
179 | #define EXIT_TB() asm volatile ("b exec_loop") | 186 | #define EXIT_TB() asm volatile ("b exec_loop") |
180 | #endif | 187 | #endif |
181 | - | 188 | +#ifdef __mc68000 |
189 | +#define EXIT_TB() asm volatile ("rts") | ||
190 | +#endif |
dyngen.c
@@ -86,6 +86,13 @@ | @@ -86,6 +86,13 @@ | ||
86 | #define elf_check_arch(x) ((x) == EM_ARM) | 86 | #define elf_check_arch(x) ((x) == EM_ARM) |
87 | #define ELF_USES_RELOC | 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 | #else | 96 | #else |
90 | #error unsupported CPU - please update the code | 97 | #error unsupported CPU - please update the code |
91 | #endif | 98 | #endif |
@@ -575,6 +582,21 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, | @@ -575,6 +582,21 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, | ||
575 | relocs, nb_relocs); | 582 | relocs, nb_relocs); |
576 | break; | 583 | break; |
577 | #endif | 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 | default: | 600 | default: |
579 | error("unknown ELF architecture"); | 601 | error("unknown ELF architecture"); |
580 | } | 602 | } |
@@ -1062,6 +1084,41 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, | @@ -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 | #else | 1122 | #else |
1066 | #error unsupported CPU | 1123 | #error unsupported CPU |
1067 | #endif | 1124 | #endif |
dyngen.h
@@ -94,6 +94,14 @@ static inline void flush_icache_range(unsigned long start, unsigned long stop) | @@ -94,6 +94,14 @@ static inline void flush_icache_range(unsigned long start, unsigned long stop) | ||
94 | } | 94 | } |
95 | #endif | 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 | #ifdef __alpha__ | 105 | #ifdef __alpha__ |
98 | 106 | ||
99 | register int gp asm("$29"); | 107 | register int gp asm("$29"); |
exec.h
@@ -348,6 +348,18 @@ static inline int testandset (int *spinlock) | @@ -348,6 +348,18 @@ static inline int testandset (int *spinlock) | ||
348 | } | 348 | } |
349 | #endif | 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 | typedef int spinlock_t; | 363 | typedef int spinlock_t; |
352 | 364 | ||
353 | #define SPIN_LOCK_UNLOCKED 0 | 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 | +} |