Commit | Line | Data |
---|---|---|
58248d62 KM |
1 | /* Copyright (c) 1984 Regents of the University of California */ |
2 | ||
3 | #ifndef lint | |
41346a4f | 4 | static char sccsid[] = "@(#)machdep.c 1.4 (Berkeley) %G%"; |
58248d62 KM |
5 | #endif not lint |
6 | ||
7 | #include <stdio.h> | |
8 | #include <ctype.h> | |
f22df3ae | 9 | #include "inline.h" |
58248d62 KM |
10 | |
11 | /* | |
f22df3ae KM |
12 | * The routines and tables in this file must be rewritten |
13 | * for each new machine that this program is ported to. | |
58248d62 KM |
14 | */ |
15 | ||
41346a4f | 16 | #ifdef vax |
f22df3ae KM |
17 | /* |
18 | * Instruction stop table. | |
19 | * All instructions that implicitly modify any of the temporary | |
20 | * registers, change control flow, or implicitly loop must be | |
21 | * listed in this table. It is used to find the end of a basic | |
22 | * block when scanning backwards through the instruction stream | |
23 | * trying to merge the inline expansion. | |
24 | */ | |
25 | struct inststoptbl inststoptable[] = { | |
26 | { "jbc" }, { "jlbc" }, { "jbs" }, { "jlbs" }, { "jbcc" }, | |
27 | { "jbsc" }, { "jbcs" }, { "jbss" }, { "jbr" }, { "jcc" }, | |
28 | { "jcs" }, { "jvc" }, { "jvs" }, { "jlss" }, { "jlssu" }, | |
29 | { "jleq" }, { "jlequ" }, { "jeql" }, { "jeqlu" }, { "jneq" }, | |
30 | { "jnequ" }, { "jgeq" }, { "jgequ" }, { "jgtr" }, { "jgtru" }, | |
31 | { "chmk" }, { "chme" }, { "chms" }, { "chmu" }, { "rei" }, | |
32 | { "ldpctx" }, { "svpctx" }, { "xfc" }, { "bpt" }, | |
33 | { "bugw" }, { "bugl" }, { "halt" }, { "pushr" }, { "popr" }, | |
34 | { "polyf" }, { "polyd" }, { "polyg" }, { "polyh" }, | |
35 | { "bneq" }, { "bnequ" }, { "beql" }, { "beqlu" }, { "bgtr" }, | |
36 | { "bleq" }, { "bgeq" }, { "blss" }, { "bgtru" }, { "blequ" }, | |
37 | { "bvc" }, { "bvs" }, { "bgequ" }, { "bcc" }, { "blssu" }, | |
38 | { "bcs" }, { "brb" }, { "brw" }, { "jmp" }, | |
39 | { "bbs" }, { "bbc" }, { "bbss" }, { "bbcs" }, { "bbsc" }, | |
40 | { "bbcc" }, { "bbssi" }, { "bbcci" }, { "blbs" }, { "blbc" }, | |
41 | { "acbb" }, { "acbw" }, { "acbl" }, { "acbf" }, { "acbd" }, | |
42 | { "acbg" }, { "acbh" }, { "aoblss" }, { "aobleq" }, | |
43 | { "sobgeq" }, { "sobgtr" }, { "caseb" }, { "casew" }, { "casel" }, | |
44 | { "bsbb" }, { "bsbw" }, { "jsb" }, { "rsb" }, | |
45 | { "callg" }, { "calls" }, { "ret" }, | |
46 | { "movc3" }, { "movc5" }, { "movtc" }, { "movtuc" }, | |
47 | { "cmpc3" }, { "cmpc5" }, { "scanc" }, { "spanc" }, | |
48 | { "locc" }, { "skpc" }, { "matchc" }, { "crc" }, | |
49 | { "movp" }, { "cmpp3" }, { "cmpp4" }, { "addp4" }, { "addp6" }, | |
50 | { "subp4" }, { "subp6" }, { "mulp" }, { "divp" }, { "cvtlp" }, | |
51 | { "cvtpl" }, { "cvtpt" }, { "cvttp" }, { "cvtps" }, { "cvtsp" }, | |
52 | { "ashp" }, { "editpc" }, | |
53 | { "escd" }, { "esce" }, { "escf" }, | |
54 | { "" } | |
55 | }; | |
56 | ||
58248d62 KM |
57 | /* |
58 | * Check to see if a line is a candidate for replacement. | |
59 | * Return pointer to name to be looked up in pattern table. | |
60 | */ | |
61 | char * | |
62 | doreplaceon(cp) | |
63 | char *cp; | |
64 | { | |
65 | ||
66 | if (bcmp(cp, "calls\t$", 7) == 0) | |
67 | return (cp + 7); | |
68 | return (0); | |
69 | } | |
70 | ||
71 | /* | |
72 | * Find the next argument to the function being expanded. | |
58248d62 KM |
73 | */ |
74 | nextarg(argc, argv) | |
75 | int argc; | |
76 | char *argv[]; | |
77 | { | |
78 | register char *lastarg = argv[2]; | |
79 | ||
80 | if (argc == 3 && | |
81 | bcmp(argv[0], "mov", 3) == 0 && | |
82 | bcmp(argv[1], "(sp)+", 6) == 0 && | |
83 | lastarg[0] == 'r' && isdigit(lastarg[1]) && lastarg[2] == '\0') | |
84 | return (lastarg[1] - '0'); | |
85 | return (-1); | |
86 | } | |
87 | ||
88 | /* | |
89 | * Determine whether the current line pushes an argument. | |
58248d62 KM |
90 | */ |
91 | ispusharg(argc, argv) | |
92 | int argc; | |
93 | char *argv[]; | |
94 | { | |
95 | ||
96 | if (argc < 2) | |
97 | return (0); | |
98 | if (argc == 2 && bcmp(argv[0], "push", 4) == 0) | |
99 | return (1); | |
100 | if (bcmp(argv[argc - 1], "-(sp)", 6) == 0) | |
101 | return (1); | |
102 | return (0); | |
103 | } | |
104 | ||
105 | /* | |
106 | * Determine which (if any) registers are modified | |
107 | * Return register number that is modified, -1 if none are modified. | |
58248d62 KM |
108 | */ |
109 | modifies(argc, argv) | |
110 | int argc; | |
111 | char *argv[]; | |
112 | { | |
113 | /* | |
114 | * For the VAX all we care about are r0 to r5 | |
115 | */ | |
116 | register char *lastarg = argv[argc - 1]; | |
117 | ||
118 | if (lastarg[0] == 'r' && isdigit(lastarg[1]) && lastarg[2] == '\0') | |
119 | return (lastarg[1] - '0'); | |
120 | return (-1); | |
121 | } | |
122 | ||
123 | /* | |
124 | * Rewrite the instruction in (argc, argv) to store its | |
125 | * contents into arg instead of onto the stack. The new | |
126 | * instruction is placed in the buffer that is provided. | |
58248d62 KM |
127 | */ |
128 | rewrite(instbuf, argc, argv, target) | |
129 | char *instbuf; | |
130 | int argc; | |
131 | char *argv[]; | |
132 | int target; | |
133 | { | |
134 | ||
135 | switch (argc) { | |
136 | case 0: | |
137 | instbuf[0] = '\0'; | |
138 | fprintf("blank line to rewrite?\n"); | |
139 | return; | |
140 | case 1: | |
141 | sprintf(instbuf, "\t%s\n", argv[0]); | |
142 | fprintf(stderr, "rewrite?-> %s", instbuf); | |
143 | return; | |
144 | case 2: | |
145 | if (bcmp(argv[0], "push", 4) == 0) { | |
146 | sprintf(instbuf, "\tmov%s\t%s,r%d\n", | |
147 | &argv[0][4], argv[1], target); | |
148 | return; | |
149 | } | |
150 | sprintf(instbuf, "\t%s\tr%d\n", argv[0], target); | |
151 | return; | |
152 | case 3: | |
153 | sprintf(instbuf, "\t%s\t%s,r%d\n", argv[0], argv[1], target); | |
154 | return; | |
155 | case 4: | |
156 | sprintf(instbuf, "\t%s\t%s,%s,r%d\n", | |
157 | argv[0], argv[1], argv[2], target); | |
158 | return; | |
52a9f051 KM |
159 | case 5: |
160 | sprintf(instbuf, "\t%s\t%s,%s,%s,r%d\n", | |
161 | argv[0], argv[1], argv[2], argv[3], target); | |
162 | return; | |
58248d62 KM |
163 | default: |
164 | sprintf(instbuf, "\t%s\t%s", argv[0], argv[1]); | |
165 | argc -= 2, argv += 2; | |
166 | while (argc-- > 0) { | |
167 | strcat(instbuf, ","); | |
168 | strcat(instbuf, *argv++); | |
169 | } | |
170 | strcat(instbuf, "\n"); | |
171 | fprintf(stderr, "rewrite?-> %s", instbuf); | |
172 | return; | |
173 | } | |
174 | } | |
41346a4f KM |
175 | |
176 | /* | |
177 | * Do any necessary post expansion cleanup. | |
178 | */ | |
179 | cleanup(numargs) | |
180 | int numargs; | |
181 | { | |
182 | ||
183 | return; | |
184 | } | |
185 | #endif vax | |
186 | ||
187 | #ifdef mc68000 | |
188 | /* | |
189 | * Instruction stop table. | |
190 | * All instructions that implicitly modify any of the temporary | |
191 | * registers, change control flow, or implicitly loop must be | |
192 | * listed in this table. It is used to find the end of a basic | |
193 | * block when scanning backwards through the instruction stream | |
194 | * trying to merge the inline expansion. | |
195 | */ | |
196 | struct inststoptbl inststoptable[] = { | |
197 | { "" } | |
198 | }; | |
199 | ||
200 | /* | |
201 | * Check to see if a line is a candidate for replacement. | |
202 | * Return pointer to name to be looked up in pattern table. | |
203 | */ | |
204 | char * | |
205 | doreplaceon(cp) | |
206 | char *cp; | |
207 | { | |
208 | ||
209 | if (bcmp(cp, "jbsr\t", 5) == 0) | |
210 | return (cp + 5); | |
211 | return (0); | |
212 | } | |
213 | ||
214 | /* | |
215 | * Find the next argument to the function being expanded. | |
216 | */ | |
217 | nextarg(argc, argv) | |
218 | int argc; | |
219 | char *argv[]; | |
220 | { | |
221 | register char *lastarg = argv[2]; | |
222 | ||
223 | if (argc == 3 && | |
224 | bcmp(argv[0], "movl", 5) == 0 && | |
225 | bcmp(argv[1], "sp@+", 5) == 0 && | |
226 | (lastarg[1] == '0' || lastarg[1] == '1') && | |
227 | lastarg[2] == '\0') { | |
228 | if (lastarg[0] == 'd') | |
229 | return (lastarg[1] - '0'); | |
230 | return (lastarg[1] - '0' + 8); | |
231 | } | |
232 | return (-1); | |
233 | } | |
234 | ||
235 | /* | |
236 | * Determine whether the current line pushes an argument. | |
237 | */ | |
238 | ispusharg(argc, argv) | |
239 | int argc; | |
240 | char *argv[]; | |
241 | { | |
242 | ||
243 | if (argc < 2) | |
244 | return (0); | |
245 | if (argc == 2 && bcmp(argv[0], "pea", 4) == 0) | |
246 | return (1); | |
247 | if (bcmp(argv[argc - 1], "sp@-", 5) == 0) | |
248 | return (1); | |
249 | return (0); | |
250 | } | |
251 | ||
252 | /* | |
253 | * Determine which (if any) registers are modified | |
254 | * Return register number that is modified, -1 if none are modified. | |
255 | */ | |
256 | modifies(argc, argv) | |
257 | int argc; | |
258 | char *argv[]; | |
259 | { | |
260 | /* | |
261 | * For the MC68000 all we care about are d0, d1, a0, and a1. | |
262 | */ | |
263 | register char *lastarg = argv[argc - 1]; | |
264 | ||
265 | if (lastarg[0] == 'd' && isdigit(lastarg[1]) && lastarg[2] == '\0') | |
266 | return (lastarg[1] - '0'); | |
267 | if (lastarg[0] == 'a' && isdigit(lastarg[1]) && lastarg[2] == '\0') | |
268 | return (lastarg[1] - '0' + 8); | |
269 | return (-1); | |
270 | } | |
271 | ||
272 | /* | |
273 | * Rewrite the instruction in (argc, argv) to store its | |
274 | * contents into arg instead of onto the stack. The new | |
275 | * instruction is placed in the buffer that is provided. | |
276 | */ | |
277 | rewrite(instbuf, argc, argv, target) | |
278 | char *instbuf; | |
279 | int argc; | |
280 | char *argv[]; | |
281 | int target; | |
282 | { | |
283 | int regno; | |
284 | char regtype; | |
285 | ||
286 | if (target < 8) { | |
287 | regtype = 'd'; | |
288 | regno = target; | |
289 | } else { | |
290 | regtype = 'a'; | |
291 | regno = target - 8; | |
292 | } | |
293 | switch (argc) { | |
294 | case 0: | |
295 | instbuf[0] = '\0'; | |
296 | fprintf("blank line to rewrite?\n"); | |
297 | return; | |
298 | case 1: | |
299 | sprintf(instbuf, "\t%s\n", argv[0]); | |
300 | fprintf(stderr, "rewrite?-> %s", instbuf); | |
301 | return; | |
302 | case 2: | |
303 | if (bcmp(argv[0], "pea", 4) == 0) { | |
304 | if (regtype == 'a') { | |
305 | sprintf(instbuf, "\tlea\t%s,%c%d\n", | |
306 | argv[1], regtype, regno); | |
307 | return; | |
308 | } | |
309 | if (argv[1][0] == '_' || isdigit(argv[1][0])) { | |
310 | sprintf(instbuf, "\tmovl\t#%s,%c%d\n", | |
311 | argv[1], regtype, regno); | |
312 | return; | |
313 | } | |
314 | sprintf(instbuf, | |
315 | "\texg\ta0,d%d\n\tlea\t%s,a0\n\texg\ta0,d%d\n", | |
316 | regno, argv[1], regno); | |
317 | return; | |
318 | } | |
319 | sprintf(instbuf, "\t%s\t%c%d\n", argv[0], regtype, regno); | |
320 | return; | |
321 | case 3: | |
322 | sprintf(instbuf, "\t%s\t%s,%c%d\n", | |
323 | argv[0], argv[1], regtype, regno); | |
324 | return; | |
325 | default: | |
326 | sprintf(instbuf, "\t%s\t%s", argv[0], argv[1]); | |
327 | argc -= 2, argv += 2; | |
328 | while (argc-- > 0) { | |
329 | strcat(instbuf, ","); | |
330 | strcat(instbuf, *argv++); | |
331 | } | |
332 | strcat(instbuf, "\n"); | |
333 | fprintf(stderr, "rewrite?-> %s", instbuf); | |
334 | return; | |
335 | } | |
336 | } | |
337 | ||
338 | /* | |
339 | * Do any necessary post expansion cleanup. | |
340 | */ | |
341 | cleanup(numargs) | |
342 | int numargs; | |
343 | { | |
344 | ||
345 | if (numargs == 0) | |
346 | return; | |
347 | /* | |
348 | * delete instruction to pop arguments. | |
349 | * TODO: | |
350 | * CHECK FOR LABEL | |
351 | * CHECK THAT INSTRUCTION IS A POP | |
352 | */ | |
353 | fgets(line[bufhead], MAXLINELEN, stdin); | |
354 | } | |
355 | #endif mc68000 |