1 /*- 2 * Copyright (c) 1984, 1986 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 */ 7 8 #ifndef lint 9 static char sccsid[] = "@(#)machdep.c 7.2 (Berkeley) 05/08/91"; 10 #endif /* not lint */ 11 12 #include <stdio.h> 13 #include <ctype.h> 14 #include "inline.h" 15 16 extern char *strcpy(); 17 extern char *strcat(); 18 extern char *index(); 19 20 /* 21 * The routines and tables in this file must be rewritten 22 * for each new machine that this program is ported to. 23 */ 24 25 #ifdef vax 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 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 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)); 96 } 97 98 /* 99 * Find the next argument to the function being expanded. 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. 117 */ 118 ispusharg(argc, argv) 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. 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. 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'; 165 fprintf(stderr, "blank line to rewrite?\n"); 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; 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; 190 default: 191 sprintf(instbuf, "\t%s\t%s", argv[0], argv[1]); 192 argc -= 2, argv += 2; 193 while (argc-- > 0) { 194 (void) strcat(instbuf, ","); 195 (void) strcat(instbuf, *argv++); 196 } 197 (void) strcat(instbuf, "\n"); 198 fprintf(stderr, "rewrite?-> %s", instbuf); 199 return; 200 } 201 } 202 203 /* 204 * Do any necessary post expansion cleanup. 205 */ 206 /*ARGSUSED*/ 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 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 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 */ 285 ispusharg(argc, argv) 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'; 343 fprintf(stderr, "blank line to rewrite?\n"); 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) { 376 (void) strcat(instbuf, ","); 377 (void) strcat(instbuf, *argv++); 378 } 379 (void) strcat(instbuf, "\n"); 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 { 391 extern int lineno; 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); 402 lineno++; 403 } 404 #endif mc68000 405