Home My Page Projects Code Snippets Project Openings SML/NJ
Summary Activity Forums Tracker Lists Tasks Docs Surveys News SCM Files

SCM Repository

[smlnj] Annotation of /sml/branches/SMLNJ/src/MLRISC/x86/emit/x86Asm.sml
ViewVC logotype

Annotation of /sml/branches/SMLNJ/src/MLRISC/x86/emit/x86Asm.sml

Parent Directory Parent Directory | Revision Log Revision Log


Revision 247 - (view) (download)

1 : monnier 247 (* x86Asm.sml -- generates GAS compatible x86 assembler
2 :     *
3 :     * COPYRIGHT (c) 1997 Bell Laboratories.
4 :     *
5 :     * $Log: X86Asm.sml,v $
6 :     * Revision 1.2 1998/08/27 14:12:11 george
7 :     * used sethi-ullman number for floating point stack
8 :     *
9 :     * Revision 1.1.1.1 1998/07/22 18:10:32 george
10 :     * X86.1
11 :     *
12 :     *)
13 :    
14 :     (* Linux uses the AT&T syntax and not the intel syntax,
15 :     * (see Using as: The GNU Assembler)
16 :     * memory operands have the form:
17 :     * section:disp(base, index, scale)
18 :     * scale in {1,2,4,8}
19 :     *)
20 :    
21 :     functor X86AsmEmitter
22 :     (structure Instr : X86INSTR
23 :     structure PseudoOps : PSEUDO_OPS
24 :     structure MemRegs : MEMORY_REGISTERS where I = Instr
25 :     structure Shuffle : X86SHUFFLE where I = Instr) =
26 :     struct
27 :     structure I = Instr
28 :     structure P = PseudoOps
29 :     structure Constant = I.Constant
30 :     structure LE = LabelExp
31 :     structure C = I.C
32 :    
33 :     fun error msg = MLRiscErrorMsg.impossible ("X86AsmEmitter." ^ msg)
34 :    
35 :     fun iToString n = if n<0 then ("-"^Int.toString (~n)) else Int.toString n
36 :     fun i32ToString n = let
37 :     val minInt = ~2147483648
38 :     in
39 :     if n=minInt then "-2147483648"
40 :     else if n<0 then ("-"^Int32.toString (~n)) else Int32.toString n
41 :     end
42 :     fun emit s = TextIO.output(!AsmStream.asmOutStream,s)
43 :     fun pseudoOp pOp = emit(P.toString pOp)
44 :     fun defineLabel(lab) = emit(Label.nameOf lab ^ ":\n")
45 :     fun comment msg = emit ("/*" ^ msg ^ "*/\n")
46 :     fun init size = comment ("Code Size = " ^ iToString size)
47 :    
48 :     fun emitInstr(instr,regmap) = let
49 :     fun rmap r = (Intmap.map regmap r) handle _ => r
50 :     val fmap = rmap
51 :     val memReg = MemRegs.memReg rmap
52 :    
53 :     fun symbolicReg 0 = "%eax"
54 :     | symbolicReg 1 = "%ecx"
55 :     | symbolicReg 2 = "%edx"
56 :     | symbolicReg 3 = "%ebx"
57 :     | symbolicReg 4 = "%esp"
58 :     | symbolicReg 5 = "%ebp"
59 :     | symbolicReg 6 = "%esi"
60 :     | symbolicReg 7 = "%edi"
61 :     | symbolicReg r = let
62 :     val r' = rmap r
63 :     in if r <> r' then symbolicReg r' else "%" ^ iToString r'
64 :     end
65 :     fun comma() = emit ", "
66 :     fun tab() = emit "\t"
67 :     fun eReg (r) = emit (symbolicReg r)
68 :     fun eFreg(f) = emit("%st(" ^ iToString(fmap f) ^ ")")
69 :    
70 :     fun eLabel lab = emit (Label.nameOf lab ^ ":")
71 :     fun newline () = emit "\n"
72 :     fun brackets f = (emit "("; f (); emit ")")
73 :    
74 :     fun emitLExp lexp = emit(LabelExp.toString lexp)
75 :    
76 :     fun eImmed(I.Immed (i)) = emit(i32ToString i)
77 :     | eImmed(I.Const c) = emit(Constant.toString c)
78 :     | eImmed(I.ImmedLabel lexp) = emitLExp lexp
79 :     | eImmed _ = error "eImmed"
80 :    
81 :     fun scaleMultiplier 0 = 1
82 :     | scaleMultiplier 1 = 2
83 :     | scaleMultiplier 2 = 4
84 :     | scaleMultiplier 3 = 8
85 :     | scaleMultiplier _ = error "scaleMultiplier"
86 :    
87 :     fun eOperand(i as I.Immed _) = (emit "$"; eImmed i)
88 :     | eOperand(I.Const c) = emit(Constant.toString c)
89 :     | eOperand(lab as I.ImmedLabel _) = (emit "$"; eImmed lab)
90 :     | eOperand(I.Direct r) = eReg r
91 :     | eOperand(f as I.FDirect fr) = let
92 :     val f' = fmap fr
93 :     in if f' < 8 then eFreg f' else eOperand(memReg f)
94 :     end
95 :     | eOperand(I.LabelEA lexp) = emitLExp lexp
96 :     | eOperand(I.Displace{base, disp=I.Immed(0)}) =
97 :     brackets(fn () => eReg base)
98 :     | eOperand(I.Displace{base, disp}) =
99 :     (eImmed disp; brackets (fn () => eReg base))
100 :     | eOperand(I.Indexed{base=NONE, index, scale, disp}) =
101 :     (eOptionalDisp disp;
102 :     brackets(fn() => (comma(); eReg index; comma();
103 :     emit(iToString (scaleMultiplier scale)))))
104 :     | eOperand(I.Indexed{base=SOME b, index, scale, disp}) =
105 :     (eOptionalDisp disp;
106 :     brackets
107 :     (fn() => (eReg b; comma(); eReg index; comma();
108 :     emit(iToString (scaleMultiplier scale)))))
109 :    
110 :     and eOptionalDisp(I.Immed(0)) = ()
111 :     | eOptionalDisp(I.Const c) = emit(Constant.toString c)
112 :     | eOptionalDisp(opnd as I.Immed _) = eImmed opnd
113 :     | eOptionalDisp _ = error "eOptionalDisp"
114 :    
115 :     (* The gas assembler does not like the "$" prefix for immediate
116 :     * labels in certain instructions.
117 :     *)
118 :     fun stupidGas(I.ImmedLabel lexp) = emitLExp lexp
119 :     | stupidGas(I.LabelEA _) = error "stupidGas"
120 :     | stupidGas opnd = eOperand opnd
121 :    
122 :     in
123 :     case instr
124 :     of I.NOP => emit "\tnop"
125 :     | I.JMP(opnd, _) => (emit"\tjmp\t"; stupidGas opnd)
126 :     | I.JCC{cond, opnd} =>
127 :     (emit
128 :     (case cond
129 :     of I.EQ => "\tje\t" | I.NE => "\tjne\t" | I.LT => "\tjl\t"
130 :     | I.LE => "\tjle\t" | I.GT => "\tjg\t" | I.GE => "\tjge\t"
131 :     | I.B => "\tjb\t" | I.BE => "\tjbe\t" | I.A => "\tja\t"
132 :     | I.AE => "\tjae\t" | I.C => "\tjc\t" | I.NC => "\tjnc\t"
133 :     | I.P => "\tjp\t" | I.NP => "\tjnp\t" | I.O => "\tjo\t"
134 :     | I.NO => "\tjno\t"
135 :     (*esac*));
136 :     stupidGas opnd)
137 :     | I.CALL(opnd,d,u) => (emit "\tcall\t"; stupidGas opnd)
138 :     (* emit ("defs=" ^ C.cellset2string d);
139 :     emit (" uses=" ^ C.cellset2string u)) *)
140 :     | I.RET => emit "\tret"
141 :     | I.MOVE{mvOp, src, dst} =>
142 :     (emit
143 :     (case mvOp
144 :     of I.MOVL => "\tmovl\t"
145 :     | I.MOVZX => "\tmovzx\t"
146 :     | I.MOVB => "\tmovb\t");
147 :     eOperand src; comma(); eOperand dst)
148 :     | I.LEA{r32, addr} =>
149 :     (emit "\tleal\t"; eOperand addr; comma(); eReg r32)
150 :     | I.CMP{lsrc, rsrc} =>
151 :     (emit "\tcmpl\t"; eOperand rsrc; comma(); eOperand lsrc)
152 :     | I.BINARY{binOp, src, dst} =>
153 :     (emit
154 :     (case binOp
155 :     of I.ADD => "\taddl\t"
156 :     | I.SUB => "\tsubl\t"
157 :     | I.AND => "\tandl\t"
158 :     | I.OR => "\torl\t"
159 :     | I.XOR => "\txorl\t"
160 :     | I.SHL => "\tshll\t"
161 :     | I.SAR => "\tsarl\t"
162 :     | I.SHR => "\tshrl\t");
163 :     eOperand src; comma(); eOperand dst)
164 :     | I.MULTDIV{multDivOp, src} =>
165 :     (emit
166 :     (case multDivOp
167 :     of I.IDIV => "\tidivl\t"
168 :     | I.UDIV => "\tdivl\t"
169 :     | I.UMUL => "\tmull\t"
170 :     (*esac*));
171 :     eOperand src)
172 :     | I.MUL3{src1, src2, dst} =>
173 :     (emit "\timul\t";
174 :     case src2
175 :     of NONE => () | SOME i => (eOperand(I.Immed(i)); comma())
176 :     (*esac*);
177 :     eOperand src1;
178 :     comma();
179 :     eOperand(I.Direct dst))
180 :     | I.UNARY{unOp, opnd} =>
181 :     (emit
182 :     (case unOp
183 :     of I.DEC => "\tdecl\t"
184 :     | I.INC => "\tincl\t"
185 :     | I.NEG => "\tnegl\t"
186 :     | I.NOT => "\tnotl\t");
187 :     eOperand opnd)
188 :     | I.PUSH opnd => (emit("\tpushl\t"); eOperand opnd)
189 :     | I.POP opnd => (emit("\tpopl\t"); eOperand opnd)
190 :     | I.CDQ => emit "\tcdq"
191 :     | I.INTO => emit "\tinto"
192 :    
193 :     | I.COPY{dst, src, tmp, ...} =>
194 :     app (fn I => (emit "\t"; emitInstr(I, regmap)))
195 :     (Shuffle.shuffle {regMap=rmap, temp=tmp, dst=dst, src=src})
196 :    
197 :     | I.FCOPY{dst, src, tmp, ...} =>
198 :     app (fn I => (emit "\t"; emitInstr(I, regmap)))
199 :     (Shuffle.shufflefp{regMap=fmap, temp=tmp, dst=dst, src=src})
200 :    
201 :     | I.FBINARY{binOp, src, dst} =>
202 :     (emit (case binOp
203 :     of I.FADDP => "\tfaddp\t" | I.FADD => "\tfadd\t"
204 :     | I.FSUB => "\tfsub\t" | I.FSUBP => "\tfsubp\t"
205 :     | I.FSUBR => "\tfsubr\t" | I.FSUBRP => "\tfsubrp\t"
206 :     | I.FMUL => "\tfmul\t" | I.FMULP => "\tfmulp\t"
207 :     | I.FDIV => "\tfdiv\t" | I.FDIVP => "\tfdivp\t"
208 :     | I.FDIVR => "\tfdivr\t" | I.FDIVRP => "\tfdivrp\t"
209 :     (*esac*));
210 :     case (src, dst)
211 :     of (I.FDirect f, _) =>
212 :     if fmap f > 7 then eOperand src (* memory location *)
213 :     else (eOperand src; comma(); eOperand dst)
214 :     | (_, I.FDirect 0) => eOperand src
215 :     (*esac*))
216 :     | I.FUNARY I.FABS => emit "\tfabs"
217 :     | I.FUNARY I.FCHS => emit "\tfchs"
218 :     | I.FXCH => emit "\tfxch"
219 :     | I.FUCOMPP => emit "\tfucompp\t"
220 :     | I.FSTP opnd => (emit "\tfstp\t"; eOperand opnd)
221 :     | I.FLD(f as I.FDirect _) => emitInstr(I.FLD(memReg f), regmap)
222 :     | I.FLD opnd => (emit "\tfld\t"; eOperand opnd)
223 :     | I.FILD opnd =>(emit "\tfild\t"; eOperand opnd)
224 :     | I.FNSTSW => emit "\tfnstsw"
225 :     | I.SAHF => emit "\tsahf"
226 :     (*esac*);
227 :     emit "\n"
228 :     end
229 :     end
230 :    
231 :    

root@smlnj-gforge.cs.uchicago.edu
ViewVC Help
Powered by ViewVC 1.0.0