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