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 | +} | ... | ... |