|
|
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.