|
|
1.1 root 1: /*
2: * n2/i386/emit1.c
3: * Prologs, etc.
4: * i386.
5: */
6:
7: #ifdef vax
8: #include "INC$LIB:cc2.h"
9: #else
10: #include "cc2.h"
11: #endif
12:
13: /* Globals. */
14: static SYM *countp;
15: ival_t framesize;
16: PREGSET usedregs;
17: int hasfloat;
18:
19: /*
20: * Generate code for the ALIGN operation.
21: * In BSS, just bump the location counter.
22: * Otherwise, write 0 bytes; note that this does not write nops,
23: * it would not work right if the alignment bytes were executed.
24: */
25: genalign(align) register int align;
26: {
27: register int n;
28:
29: if (align == 0)
30: return; /* ignore ALIGN 0 */
31: if (isvariant(VASM)) {
32: bput(ALIGN); bput(align);
33: return;
34: }
35: n = dot & (align-1); /* excess past alignment boundary */
36: if (n == 0)
37: return;
38: n = align - n; /* bump to next boundary */
39: if (dotseg == SBSS)
40: dot += n;
41: else
42: outnzb((sizeof_t)n, (dotseg == SCODE));
43: }
44:
45: /*
46: * Generate code for a function prolog.
47: * The prolog is generally of the form
48: * mov ebp, esp
49: * sub ebp, $framesize
50: * push esi
51: * push edi
52: * push ebx
53: * with variations for profiling and framesize.
54: * Saving the registers after the local adjust allows suppressing the
55: * register save/restore if the function does not touch the register.
56: */
57: genprolog()
58: {
59: register int lab;
60: register SYM *labp;
61:
62: hasfloat = 0;
63: if (isvariant(VASM)) {
64: /* Write assembler. */
65: if ((framesize == 0) || (framesize >= 65536L) || isvariant(VPROF)) {
66: genone(ZPUSH, A_REBP);
67: gentwo(ZMOV, A_REBP, A_RESP);
68: }
69: if (isvariant(VPROF)) {
70: genseg(SBSS);
71: bput(LLABEL); iput((ival_t)(lab=newlab()));
72: genblock((sizeof_t)12);
73: genseg(SCODE);
74: gentwo(ZMOV, A_RECX, A_IMM|A_LID, lab);
75: genone(ZCALL, A_GID|A_DIR, "_scount");
76: }
77: if (framesize != 0) {
78: if (notvariant(VPROF) && framesize < 65536L)
79: gentwo(ZENTER, A_IMM|A_OFFS, framesize, A_IMM|A_OFFS, (ival_t)0);
80: else {
81: if (framesize <= 4)
82: genone(ZPUSH, A_REAX);
83: else
84: gentwo(ZSUB, A_RESP, A_OFFS|A_IMM, framesize);
85: }
86: }
87: if ((usedregs & BESI) != 0)
88: genone(ZPUSH, A_RESI);
89: if ((usedregs & BEDI) != 0)
90: genone(ZPUSH, A_REDI);
91: if ((usedregs & BEBX) != 0)
92: genone(ZPUSH, A_REBX);
93: } else {
94: /* Write bits. */
95: if ((framesize == 0) || (framesize >= 65536L) || isvariant(VPROF)) {
96: outab(0x55); /* push ebp */
97: outab(0x8B); outab(0xEC); /* mov ebp, esp */
98: }
99: if (isvariant(VPROF)) {
100: genseg(SBSS);
101: labp = llookup(newlab(), 1);
102: labp->s_seg = dotseg;
103: labp->s_value = dot;
104: genblock((sizeof_t)12);
105: genseg(SCODE);
106: outab(0xB9); /* mov ecx, offset lab */
107: outxl(labp, 0, 0);
108: if (countp == NULL)
109: countp = glookup("_scount", 0);
110: outab(0xE8); /* call _scount */
111: outxl(countp, 0, 1);
112: }
113: if (framesize != 0) {
114: if (notvariant(VPROF) && framesize < 65536L) {
115: outab(0xC8); /* enter framesize,0 */
116: outaw(framesize);
117: outab(0);
118: } else {
119: if (framesize == 4)
120: outab(0x50); /* push eax */
121: else {
122: if (framesize >= 128)
123: outab(0x81); /* sub, sw=01 */
124: else
125: outab(0x83); /* sub, sw=11 */
126: outab(0xEC); /* esp, */
127: if (framesize < 128)
128: outab(framesize); /* value */
129: else
130: outal(framesize);
131: }
132: }
133: }
134: if ((usedregs & BESI) != 0)
135: outab(0x56); /* push esi */
136: if ((usedregs & BEDI) != 0)
137: outab(0x57); /* push edi */
138: if ((usedregs & BEBX) != 0)
139: outab(0x53); /* push ebx */
140: }
141: }
142:
143: /*
144: * Generate code for a function epilog.
145: * If NDP, the variable 'hasfloat' keeps track of whether the function performs
146: * floating point operations.
147: * If it does, the epilogue includes an FWAIT to assure completion;
148: * otherwise, a store into a local variable could complete after the exit,
149: * when the allocated stack space has been reused for something else.
150: * The peephole optimizer knows the details of epilogue code generation,
151: * because it suppresses a stack adjust which immediately precedes LEAVE;
152: * if the generated code here changes, change i386/peep.c/noeffect() too.
153: */
154: genepilog()
155: {
156: if (isvariant(VASM)) {
157: if (isvariant(VNDP) && hasfloat) {
158: #if 0
159: if (isvariant(VEMU87))
160: genone(ZCALL, A_GID|A_DIR, "emu87");
161: else {
162: #endif
163: bput(CODE); bput(ZFWAIT);
164: #if 0
165: }
166: #endif
167: }
168: if ((usedregs & BEBX) != 0)
169: genone(ZPOP, A_REBX);
170: if ((usedregs & BEDI) != 0)
171: genone(ZPOP, A_REDI);
172: if ((usedregs & BESI) != 0)
173: genone(ZPOP, A_RESI);
174: bput(CODE); bput(ZLEAVE);
175: bput(CODE); bput(ZRET);
176: } else {
177: if (isvariant(VNDP) && hasfloat) {
178: #if 0
179: if (isvariant(VEMU87))
180: outemucall(); /* call emu87 */
181: else
182: #endif
183: outfb(0x9B); /* fwait */
184: }
185: if ((usedregs & BEBX) != 0)
186: outab(0x5B); /* pop ebx */
187: if ((usedregs & BEDI) != 0)
188: outab(0x5F); /* pop edi */
189: if ((usedregs & BESI) != 0)
190: outab(0x5E); /* pop esi */
191: outab(0xC9); /* leave */
192: outab(0xC3); /* ret */
193: }
194: genalign(4);
195: }
196:
197: /*
198: * Generate the code for a BLOCK item.
199: * If in -S mode, output an assembly directive to get the space.
200: * If generating binary, bump 'dot' if compiling into BSS;
201: * otherwise, output a block of 0 bytes.
202: */
203: genblock(n) register sizeof_t n;
204: {
205: if (isvariant(VASM)) {
206: bput(BLOCK); zput(n);
207: } else if (dotseg == SBSS)
208: dot += n;
209: else
210: outnzb(n, 0);
211: }
212:
213: /* end of n2/i386/emit1.c */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.