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