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