|
|
1.1 ! root 1: /* ! 2: * n3/i386/icode.c ! 3: * Machine dependent parts of the intermediate file printer. ! 4: * Read and print encoded machine instructions and operands. ! 5: * Includes tables of opcodes and register names. ! 6: * i386. ! 7: */ ! 8: ! 9: #ifdef vax ! 10: #include "INC$LIB:cc3.h" ! 11: #else ! 12: #include "cc3.h" ! 13: #endif ! 14: ! 15: /* ! 16: * Opcode names which depend on assembler format. ! 17: */ ! 18: ! 19: #if AS_FORMAT ! 20: #define ICALL "icall" ! 21: #define IJMP "ijmp" ! 22: #define XICALL "licall" ! 23: #define XIJMP "lijmp" ! 24: #define XCALL "lcall" ! 25: #define XJMP "ljmp" ! 26: #define XRET "lret" ! 27: #define DBYTE ".byte" ! 28: #define DWORD ".word" ! 29: #define DLONG ".long" ! 30: #else ! 31: #define ICALL "call" ! 32: #define IJMP "jmp" ! 33: #define XICALL "call" ! 34: #define XIJMP "jmp" ! 35: #define XCALL "call" ! 36: #define XJMP "jmp" ! 37: #define XRET "ret" ! 38: #define DBYTE ".db" ! 39: #define DWORD ".dw" ! 40: #define DLONG ".dd" ! 41: #endif ! 42: ! 43: /* ! 44: * Instruction names, sizes, and flags. ! 45: * This table is ordered according to h/i8086/opcode.h ! 46: * and thus parallel to n2/i8086/opcode.c. ! 47: * Modifications to any of these require modifications to all of them. ! 48: */ ! 49: static struct ins { ! 50: char *i_name; ! 51: char i_size; ! 52: char i_flag; ! 53: } ins[] = { ! 54: "adc", 2, 0, ! 55: "addl", 2, 0, ! 56: "addb", 2, OP_BYTE, ! 57: "addw", 2, OP_WORD, ! 58: "andl", 2, 0, ! 59: "andb", 2, OP_BYTE, ! 60: "andw", 2, OP_WORD, ! 61: "call", 1, OP_NPTR, ! 62: "cbw", 0, OP_WORD, ! 63: "cdq", 0, 0, ! 64: "clc", 0, 0, ! 65: "cld", 0, 0, ! 66: "cli", 0, 0, ! 67: "cmc", 0, 0, ! 68: "cmpl", 2, 0, ! 69: "cmpb", 2, OP_BYTE, ! 70: "cmpw", 2, OP_WORD, ! 71: "cmpsw", 0, 0, ! 72: "cmpsb", 0, 0, ! 73: "cmpsw", 0, OP_WORD, ! 74: "cwd", 0, OP_WORD, ! 75: "cwde", 0, 0, ! 76: "decl", 1, 0, ! 77: "decb", 1, OP_BYTE, ! 78: "decw", 1, OP_WORD, ! 79: "divl", 1, 0, ! 80: "divb", 1, OP_BYTE, ! 81: "divw", 1, OP_WORD, ! 82: "enter", 2, 0, ! 83: "hlt", 0, 0, ! 84: ICALL, 1, 0, ! 85: "idivl", 1, 0, ! 86: "idivb", 1, OP_BYTE, ! 87: "idivw", 1, OP_WORD, ! 88: IJMP, 1, 0, ! 89: "imull", 1, 0, ! 90: "imulb", 1, OP_BYTE, ! 91: "imulw", 1, OP_WORD, ! 92: "imul", 3, 0, ! 93: "incl", 1, 0, ! 94: "incb", 1, OP_BYTE, ! 95: "incw", 1, OP_WORD, ! 96: "iret", 0, 0, ! 97: XICALL, 1, OP_DWORD, ! 98: XIJMP, 1, OP_NPTR, ! 99: "ja", 1, OP_JUMP, ! 100: "jae", 1, OP_JUMP, ! 101: "jb", 1, OP_JUMP, ! 102: "jbe", 1, OP_JUMP, ! 103: "jcxz", 1, OP_JUMP, ! 104: "je", 1, OP_JUMP, ! 105: "jg", 1, OP_JUMP, ! 106: "jge", 1, OP_JUMP, ! 107: "jl", 1, OP_JUMP, ! 108: "jle", 1, OP_JUMP, ! 109: "jmp", 1, OP_JUMP, ! 110: "jne", 1, OP_JUMP, ! 111: "jno", 1, OP_JUMP, ! 112: "jns", 1, OP_JUMP, ! 113: "jo", 1, OP_JUMP, ! 114: "jpe", 1, OP_JUMP, ! 115: "jpo", 1, OP_JUMP, ! 116: "js", 1, OP_JUMP, ! 117: "lea", 2, 0, ! 118: "leave", 0, 0, ! 119: "lock", 0, 0, ! 120: "lodsw", 0, 0, ! 121: "lodsb", 0, 0, ! 122: "loop", 1, OP_JUMP, ! 123: "loope", 1, OP_JUMP, ! 124: "loopne", 1, OP_JUMP, ! 125: "movl", 2, 0, ! 126: "movb", 2, OP_BYTE, ! 127: "movw", 2, OP_WORD, ! 128: "movsw", 0, 0, ! 129: "movsb", 0, 0, ! 130: "movsxw", 2, 0, ! 131: "movsxb", 2, OP_BYTE, ! 132: "movzxw", 2, 0, ! 133: "movzxb", 2, OP_BYTE, ! 134: "mull", 1, 0, ! 135: "mulb", 1, OP_BYTE, ! 136: "mulw", 1, OP_WORD, ! 137: "negl", 1, 0, ! 138: "negb", 1, OP_BYTE, ! 139: "negw", 1, OP_WORD, ! 140: "notl", 1, 0, ! 141: "notb", 1, OP_BYTE, ! 142: "notw", 1, OP_WORD, ! 143: "ret", 1, OP_NPTR, ! 144: "ret", 1, OP_NPTR, ! 145: "orl", 2, 0, ! 146: "orb", 2, OP_BYTE, ! 147: "orw", 2, OP_WORD, ! 148: "pop", 1, 0, ! 149: "popf", 0, 0, ! 150: "push", 1, 0, ! 151: "pushf", 0, 0, ! 152: "rcl", 2, 0, ! 153: "rclb", 2, OP_BYTE, ! 154: "rcr", 2, 0, ! 155: "rcrb", 2, OP_BYTE, ! 156: "repe", 0, 0, ! 157: "repne", 0, 0, ! 158: "ret", 0, 0, ! 159: "rol", 2, 0, ! 160: "rolb", 2, OP_BYTE, ! 161: "ror", 2, 0, ! 162: "rorb", 2, OP_BYTE, ! 163: "sall", 2, 0, ! 164: "salb", 2, OP_BYTE, ! 165: "salw", 2, OP_WORD, ! 166: "sarl", 2, 0, ! 167: "sarb", 2, OP_BYTE, ! 168: "sarw", 2, OP_WORD, ! 169: "sbb", 2, 0, ! 170: "scasw", 0, 0, ! 171: "scasb", 0, 0, ! 172: "shll", 2, 0, ! 173: "shlb", 2, OP_BYTE, ! 174: "shlw", 2, OP_WORD, ! 175: "shrl", 2, 0, ! 176: "shrb", 2, OP_BYTE, ! 177: "shrw", 2, OP_WORD, ! 178: "stc", 0, 0, ! 179: "std", 0, 0, ! 180: "sti", 0, 0, ! 181: "stosw", 0, 0, ! 182: "stosb", 0, 0, ! 183: "subl", 2, 0, ! 184: "subb", 2, OP_BYTE, ! 185: "subw", 2, OP_WORD, ! 186: "testl", 2, 0, ! 187: "testb", 2, OP_BYTE, ! 188: "testw", 2, OP_WORD, ! 189: "wait", 0, 0, ! 190: XCALL, 1, OP_NPTR, ! 191: "xchg", 2, 0, ! 192: "xchgb", 2, OP_BYTE, ! 193: XJMP, 1, OP_NPTR, ! 194: "xorl", 2, 0, ! 195: "xorb", 2, OP_BYTE, ! 196: "xorw", 2, OP_WORD, ! 197: XRET, 0, 0, ! 198: ! 199: /* Specials. */ ! 200: DBYTE, 1, OP_DD|OP_NPTR, ! 201: DWORD, 1, OP_DD|OP_NPTR, ! 202: DLONG, 1, OP_DD|OP_NPTR, ! 203: DLONG, 1, OP_DD|OP_NPTR, ! 204: DLONG, 1, OP_DD|OP_NPTR, ! 205: ! 206: /* Old, now unused. */ ! 207: #if 0 ! 208: "aaa", 0, 0, ! 209: "aad", 0, 0, ! 210: "aam", 0, 0, ! 211: "aas", 0, 0, ! 212: "adcb", 2, OP_BYTE, ! 213: "daa", 0, 0, ! 214: "das", 0, 0, ! 215: "in", 1, 0, ! 216: "inb", 1, OP_BYTE, ! 217: "int", 1, OP_NPTR, ! 218: "into", 0, 0, ! 219: "lahf", 0, 0, ! 220: "lds", 2, OP_DWORD, ! 221: "les", 2, OP_DWORD, ! 222: "out", 1, 0, ! 223: "outb", 1, OP_BYTE, ! 224: "sahf", 0, 0, ! 225: "sbbb", 2, OP_BYTE, ! 226: "xlat", 0, 0, ! 227: #endif ! 228: ! 229: #if 1 ! 230: "faddl", 1, 0, ! 231: "fadds", 1, 0, ! 232: "fiaddl", 1, 0, ! 233: "fiadds", 1, 0, ! 234: "fsubl", 1, 0, ! 235: "fsubs", 1, 0, ! 236: "fisubl", 1, 0, ! 237: "fisubs", 1, 0, ! 238: "fsubrl", 1, 0, ! 239: "fsubrs", 1, 0, ! 240: "fisubrl", 1, 0, ! 241: "fisubrs", 1, 0, ! 242: "fcomp", 0, 0, ! 243: "fcompl", 1, 0, ! 244: "fcomps", 1, 0, ! 245: "ficompl", 1, 0, ! 246: "ficomps", 1, 0, ! 247: "fmull", 1, 0, ! 248: "fmuls", 1, 0, ! 249: "fimull", 1, 0, ! 250: "fimuls", 1, 0, ! 251: "fdivl", 1, 0, ! 252: "fdivs", 1, 0, ! 253: "fidivl", 1, 0, ! 254: "fidivs", 1, 0, ! 255: "fdivrl", 1, 0, ! 256: "fdivrs", 1, 0, ! 257: "fidivrl", 1, 0, ! 258: "fidivrs", 1, 0, ! 259: "fchs", 0, 0, ! 260: "ftst", 0, 0, ! 261: "fldz", 0, 0, ! 262: "fld1", 0, 0, ! 263: "fstsw", 1, 0, ! 264: "fldl", 1, 0, ! 265: "flds", 1, 0, ! 266: "fildl", 1, 0, ! 267: "filds", 1, 0, ! 268: "fldt", 1, 0, ! 269: "fstl", 1, 0, ! 270: "fsts", 1, 0, ! 271: "fistl", 1, 0, ! 272: "fists", 1, 0, ! 273: "fstpl", 1, 0, ! 274: "fstps", 1, 0, ! 275: "fistpl", 1, 0, ! 276: "fistps", 1, 0, ! 277: "fstpt", 1, 0, ! 278: "fwait", 0, 0, ! 279: #if 0 ! 280: "fdrop", 0, 0, ! 281: #else ! 282: "fstp\t%st", 0, 0, ! 283: #endif ! 284: ! 285: /* Old, now unused. */ ! 286: #if 0 ! 287: "fadd", 0, 0, ! 288: "fsub", 0, 0, ! 289: "frsub", 0, 0, ! 290: "fmul", 0, 0, ! 291: "fdiv", 0, 0, ! 292: "frdiv", 0, 0, ! 293: #endif ! 294: #endif ! 295: }; ! 296: ! 297: /* ! 298: * Handle code nodes. ! 299: */ ! 300: icode() ! 301: { ! 302: register int op, i, n; ! 303: register struct ins *ip; ! 304: ! 305: op = bget(); ! 306: if (dotseg == SSTRN && op == ZBYTE) { ! 307: istring(); ! 308: return; ! 309: } ! 310: ip = &ins[op]; ! 311: bput('\t'); ! 312: #if 0 ! 313: if (ip->i_flag & OP_WORD) ! 314: fprintf(ofp, "pfx16:\t"); ! 315: #endif ! 316: fputs(ip->i_name, ofp); ! 317: n = ip->i_size; ! 318: for (i = 0; i < n; i += 1) { ! 319: if (i == 0) { ! 320: bput('\t'); ! 321: } else ! 322: fputs(", ", ofp); ! 323: iafield(ip); ! 324: } ! 325: bput('\n'); ! 326: } ! 327: ! 328: /* ! 329: * Print a string for the assembler. ! 330: * The first ZBYTE op has already been read before the call. ! 331: */ ! 332: istring() ! 333: { ! 334: register int imode, c, op; ! 335: ! 336: fputs("\t.byte\t\"", ofp); ! 337: for(;;) { ! 338: if (((imode = iget()) & A_AMOD) != A_DIR) ! 339: cbotch("istring: imode=%d\n", imode); ! 340: c = ((imode & A_OFFS) != 0) ? iget() : 0; ! 341: if (c == '\0') { ! 342: fprintf(ofp, "\", 0\n"); ! 343: return; ! 344: } else if (c == '\n') ! 345: fprintf(ofp, "\\n"); ! 346: else if (c < ' ' || c > 0x7F) ! 347: fprintf(ofp, "\\%03o", c); ! 348: else ! 349: bput(c); ! 350: if ((op = bget()) != CODE) { ! 351: unbget(op); ! 352: break; ! 353: } else if ((op = bget()) != ZBYTE) ! 354: cbotch("istring: %x\n", op); ! 355: } ! 356: fputs("\"\n", ofp); ! 357: } ! 358: ! 359: /* ! 360: * These tables are indexed by the regm field of a mode. ! 361: * They contain the ASCII strings used to print reg names in VASM mode. ! 362: */ ! 363: static char *dregs[] = { ! 364: "%eax", "%ecx", "%edx", "%ebx", "%esp", "%ebp", "%esi", "%edi" ! 365: }; ! 366: ! 367: static char *wregs[] = { ! 368: "%ax", "%cx", "%dx", "%bx", "%sp", "%bp", "%si", "%di" ! 369: }; ! 370: ! 371: static char *bregs[] = { ! 372: "%al", "%cl", "%dl", "%bl", "%ah", "%ch", "%dh", "%bh" ! 373: }; ! 374: ! 375: static int scale[] = { ! 376: 1, 2, 4, 8 ! 377: }; ! 378: ! 379: /* ! 380: * Read and print an address field. ! 381: * The style of the address is determined by flag bits in the address mode. ! 382: * These bits are cleared away when the mode is actually stored in the afield. ! 383: */ ! 384: iafield(ip) ! 385: register struct ins *ip; ! 386: { ! 387: register int imode, mode, regm, flag; ! 388: register ival_t offs; ! 389: ! 390: imode = iget(); ! 391: if ((imode & A_OFFS) != 0) ! 392: offs = iget(); ! 393: else ! 394: offs = (ival_t)0; ! 395: if ((imode & A_LID) != 0) ! 396: sprintf(id, ".L%d", (int)iget()); ! 397: else if ((imode & A_GID) != 0) ! 398: sget(id, NCSYMB); ! 399: mode = imode & A_AMOD; ! 400: if ((mode & A_X) != 0) ! 401: mode = A_X; /* indexed in some form */ ! 402: regm = imode & A_REGM; ! 403: flag = ip->i_flag; ! 404: switch (mode) { ! 405: ! 406: case A_IMM: ! 407: #if AS_FORMAT ! 408: bput('$'); ! 409: #else ! 410: if ((imode & (A_LID|A_GID)) != 0) ! 411: fprintf(ofp, "offset "); ! 412: #endif ! 413: /* fall through... */ ! 414: case A_DIR: ! 415: case A_X: ! 416: /* Immediate, direct, indexed, all in one grungy case. */ ! 417: #if !AS_FORMAT ! 418: if (mode!=A_IMM && (flag&OP_NPTR)==0) { ! 419: if ((flag&OP_BYTE) != 0) ! 420: fprintf(ofp, "byte"); ! 421: else if ((flag&OP_WORD) != 0) ! 422: fprintf(ofp, "word"); ! 423: else ! 424: fprintf(ofp, "dword"); ! 425: fprintf(ofp, " ptr "); ! 426: } ! 427: if (mode == A_X) { ! 428: bput('['); ! 429: if ((imode & A_AMOD) == A_XB) ! 430: fprintf(ofp, "%s", dregs[regm]); ! 431: else if ((imode & A_AMOD) == A_XSIB) { ! 432: if (regm != 5) ! 433: fprintf(ofp, "%s", dregs[regm]); ! 434: fprintf(ofp, ", %s, %d", ! 435: dregs[IREG(imode)], ! 436: scale[SCALE(imode)]); ! 437: } ! 438: } ! 439: #endif ! 440: if ((imode & (A_LID|A_GID)) != 0) { ! 441: /* Symbol-relative. */ ! 442: #if !AS_FORMAT ! 443: if (mode == A_X) ! 444: bput('+'); ! 445: #endif ! 446: fputs(id, ofp); ! 447: if ((SIGNEDADDRESS)offs > 0) ! 448: bput('+'); ! 449: } ! 450: #if !AS_FORMAT ! 451: else if (mode==A_X && (SIGNEDADDRESS)offs>0) ! 452: bput('+'); ! 453: #endif ! 454: if (offs!=0 || ((imode & (A_LID|A_GID))==0 && mode!=A_X)) { ! 455: #if AS_FORMAT ! 456: fprintf(ofp, I_FMT, offs); ! 457: #else ! 458: if ((SIGNEDADDRESS)offs<0) { ! 459: bput('-'); ! 460: offs = -(SIGNEDADDRESS)offs; ! 461: } ! 462: fprintf(ofp, "0" I_FMTX "h", offs); ! 463: #endif ! 464: } ! 465: if (mode == A_X) { ! 466: #if AS_FORMAT ! 467: bput('('); ! 468: if ((imode & A_AMOD) == A_XB) ! 469: fprintf(ofp, "%s", dregs[regm]); ! 470: else if ((imode & A_AMOD) == A_XSIB) { ! 471: if (regm != 5) ! 472: fprintf(ofp, "%s", dregs[regm]); ! 473: fprintf(ofp, ", %s, %d", ! 474: dregs[IREG(imode)], ! 475: scale[SCALE(imode)]); ! 476: } ! 477: bput(')'); ! 478: #else ! 479: bput(']'); ! 480: #endif ! 481: } ! 482: break; ! 483: ! 484: case A_DR: ! 485: fputs(dregs[regm], ofp); ! 486: break; ! 487: ! 488: case A_WR: ! 489: fputs(wregs[regm], ofp); ! 490: break; ! 491: ! 492: case A_BR: ! 493: fputs(bregs[regm], ofp); ! 494: break; ! 495: ! 496: default: ! 497: cbotch("ifield, mode=%d", mode); ! 498: } ! 499: } ! 500: ! 501: /* end of n3/i386/icode.c */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.