JNAsm implementation in progress.
[jnode:svn-mirror.git] / builder / src / builder / org / jnode / jnasm / assembler / x86 / X86Core.java
1 /**
2  * $Id$  
3  */
4 package org.jnode.jnasm.assembler.x86;
5
6 import org.jnode.jnasm.assembler.AssemblerModule;
7 import org.jnode.jnasm.assembler.Token;
8 import org.jnode.jnasm.assembler.Indirect;
9 import org.jnode.jnasm.assembler.Assembler;
10 import org.jnode.jnasm.assembler.InstructionUtils;
11 import org.jnode.assembler.x86.X86Assembler;
12 import org.jnode.assembler.x86.X86Constants;
13 import org.jnode.assembler.x86.X86Register;
14 import org.jnode.assembler.Label;
15 import org.jnode.assembler.NativeStream;
16
17 import java.util.Map;
18 import java.util.List;
19
20 /**
21  * @author Levente S\u00e1ntha
22  */
23 public class X86Core extends AssemblerModule {
24     private static final int NUL_ARG = 0;
25     private static final int CON_ARG = 1;
26     private static final int REG_ARG = 2;
27     private static final int IND_ARG = 3;
28     private static final int DISP = 2;
29
30     private static final int N_ADDR = NUL_ARG;
31     private static final int C_ADDR = CON_ARG;
32     private static final int R_ADDR = REG_ARG;
33     private static final int RR_ADDR = REG_ARG | REG_ARG << DISP;
34     private static final int RC_ADDR = REG_ARG | CON_ARG << DISP;
35     private static final int RI_ADDR = REG_ARG | IND_ARG << DISP;
36     private static final int I_ADDR = IND_ARG;
37     private static final int IR_ADDR = IND_ARG | REG_ARG << DISP;
38     private static final int IC_ADDR = IND_ARG | CON_ARG << DISP;
39
40     private static final String[] ARG_TYPES = {"noargument","constant","register","indirect"};
41
42     private final Object[] args = new Object[3];
43
44
45
46     private int getAddressingMode(int maxArgs) {
47         int ret = N_ADDR;
48         if (maxArgs > 3) {
49             throw new Error("Invalid number of arguments: " + maxArgs);
50         }
51
52         for (int i = 0; i < maxArgs; i++) {
53             try {
54                 if(operands == null) break;
55                 
56                 Object o = operands.get(i);
57                 if (o == null) break;
58
59                 if (o instanceof Integer) {
60                     ret |= CON_ARG << 2 * i;
61                 } else if (o instanceof Token && Assembler.isIdent((Token) o)) {
62                     ret |= REG_ARG << 2 * i;
63                 } else if (o instanceof Indirect) {
64                     ret |= IND_ARG << 2 * i;
65                 } else {
66                     System.out.println("unkown operand: " + o);
67                 }
68
69                 args[i] = o;
70
71             } catch (IndexOutOfBoundsException x) {
72                 break;
73             }
74         }
75         return ret;
76     }
77
78     private final int getInt(int i) {
79         return ((Integer) args[i]).intValue();
80     }
81
82     private final X86Register.GPR getReg(int i) {
83         return getRegister((Token) args[i]);
84     }
85
86     private final Indirect getInd(int i) {
87         return (Indirect) args[i];
88     }
89
90
91     public static final int ADD_ISN = 0;
92     public static final int AND_ISN = ADD_ISN + 1;
93     public static final int CMP_ISN = AND_ISN + 1;
94     public static final int DEC_ISN = CMP_ISN + 1;
95     public static final int INC_ISN = DEC_ISN + 1;
96     public static final int JMP_ISN = INC_ISN + 1;
97     public static final int LEA_ISN = JMP_ISN + 1;
98     public static final int MOV_ISN = LEA_ISN + 1;
99     public static final int NOP_ISN = MOV_ISN + 1;
100     public static final int OR_ISN = NOP_ISN + 1;
101     public static final int POP_ISN = OR_ISN + 1;
102     public static final int PUSH_ISN = POP_ISN + 1;
103     public static final int RET_ISN = PUSH_ISN + 1;
104     public static final int SHR_ISN = RET_ISN + 1;
105     public static final int TEST_ISN = SHR_ISN + 1;
106     public static final int XCHG_ISN = TEST_ISN + 1;
107     public static final int XOR_ISN = XCHG_ISN + 1;
108
109
110     protected static final Map INSTRUCTION_MAP;
111     private static final String[] MNEMONICS;
112
113     static {
114         Map map = InstructionUtils.getInstructionMap(X86Core.class);
115         String[] mnemonics = InstructionUtils.getMnemonicArray(map);
116         INSTRUCTION_MAP = map;
117         MNEMONICS = mnemonics;
118     }
119
120     private List operands;
121     private X86Assembler stream;
122
123     public X86Core(final Map labels) {
124         super(labels);
125     }
126
127     public void setNativeStream(NativeStream stream) {
128         this.stream = (X86Assembler) stream;
129     }
130
131     public boolean emmit(String mnemonic, List operands) {
132         this.operands = operands;
133
134         Integer key = (Integer) INSTRUCTION_MAP.get(mnemonic);
135
136         if (key == null) return false;
137
138         switch (key.intValue()) {
139             case ADD_ISN:
140                 emmitADD();
141                 break;
142             case AND_ISN:
143                 emmitAND();
144                 break;
145             case CMP_ISN:
146                 emmitCMP();
147                 break;
148             case DEC_ISN:
149                 emmitDEC();
150                 break;
151             case INC_ISN:
152                 emmitINC();
153                 break;
154             case JMP_ISN:
155                 emmitJMP();
156                 break;
157             case LEA_ISN:
158                 emmitLEA();
159                 break;
160             case MOV_ISN:
161                 emmitMOV();
162                 break;
163             case NOP_ISN:
164                 emmitNOP();
165                 break;
166             case OR_ISN:
167                 emmitOR();
168                 break;
169             case POP_ISN:
170                 emmitPOP();
171                 break;
172             case PUSH_ISN:
173                 emmitPUSH();
174                 break;
175             case RET_ISN:
176                 emmitRET();
177                 break;
178             case SHR_ISN:
179                 emmitSHR();
180                 break;
181             case TEST_ISN:
182                 emmitTEST();
183                 break;
184             case XCHG_ISN:
185                 emmitXCHG();
186                 break;
187             case XOR_ISN:
188                 emmitXOR();
189                 break;
190             default:
191                 throw new Error("Invalid instruction binding " + key.intValue() + " for " + mnemonic);
192         }
193
194         return true;
195     }
196
197     private void emmitADD() {
198         int addr = getAddressingMode(2);
199         switch (addr) {
200             case RR_ADDR:
201                 stream.writeADD(getReg(0), getReg(1));
202                 break;
203             case RC_ADDR:
204                 stream.writeADD(getReg(0), getInt(1));
205                 break;
206             case RI_ADDR:
207                 Indirect ind = getInd(1);
208                 stream.writeADD(getReg(0), getRegister(ind.reg), ind.disp);
209                 break;
210             case IR_ADDR:
211                 ind = getInd(0);
212                 stream.writeADD(getRegister(ind.reg), ind.disp, getReg(1));
213                 break;
214             case IC_ADDR:
215                 ind = getInd(0);
216                 stream.writeADD(X86Constants.BITS32, getRegister(ind.reg), ind.disp, getInt(1));
217                 break;
218             default:
219                 reportAddressingError(ADD_ISN, addr);
220         }
221     }
222
223     private void emmitAND() {
224         int addr = getAddressingMode(2);
225         switch (addr) {
226             case RR_ADDR:
227                 stream.writeAND(getReg(0), getReg(1));
228                 break;
229             case RC_ADDR:
230                 stream.writeAND(getReg(0), getInt(1));
231                 break;
232             case RI_ADDR:
233                 Indirect ind = getInd(1);
234                 stream.writeAND(getReg(0), getRegister(ind.reg), ind.disp);
235                 break;
236             case IR_ADDR:
237                 ind = getInd(0);
238                 stream.writeAND(getRegister(ind.reg), ind.disp, getReg(1));
239                 break;
240             case IC_ADDR:
241                 ind = getInd(0);
242                 stream.writeAND(X86Constants.BITS32, getRegister(ind.reg), ind.disp, getInt(1));
243                 break;
244             default:
245                 reportAddressingError(AND_ISN, addr);
246         }
247     }
248
249     private void emmitCMP() {
250         int addr = getAddressingMode(2);
251         switch (addr) {
252             case RR_ADDR:
253                 stream.writeCMP(getReg(0), getReg(1));
254                 break;
255             case RC_ADDR:
256                 stream.writeCMP_Const(getReg(0), getInt(1));
257                 break;
258             case RI_ADDR:
259                 Indirect ind = getInd(1);
260                 stream.writeCMP(getReg(0), getRegister(ind.reg), ind.disp);
261                 break;
262             case IR_ADDR:
263                 ind = getInd(0);
264                 stream.writeCMP(getRegister(ind.reg), ind.disp, getReg(1));
265                 break;
266             case IC_ADDR:
267                 ind = getInd(0);
268                 stream.writeCMP_Const(X86Constants.BITS32, getRegister(ind.reg), ind.disp, getInt(1));
269                 break;
270             default:
271                 reportAddressingError(CMP_ISN, addr);
272         }
273     }
274
275     private void emmitDEC() {
276         int addr = getAddressingMode(1);
277         switch (addr) {
278             case R_ADDR:
279                 stream.writeDEC(getReg(0));
280                 break;
281             case I_ADDR:
282                 Indirect ind = getInd(0);
283                 stream.writeDEC(X86Constants.BITS32, getRegister(ind.reg), ind.disp);
284                 break;
285             default:
286                 reportAddressingError(DEC_ISN, addr);
287         }
288     }
289
290     private void emmitINC() {
291         int addr = getAddressingMode(1);
292         switch (addr) {
293             case R_ADDR:
294                 stream.writeINC(getReg(0));
295                 break;
296             case I_ADDR:
297                 Indirect ind = getInd(0);
298                 stream.writeINC(X86Constants.BITS32, getRegister(ind.reg), ind.disp);
299                 break;
300             default:
301                 reportAddressingError(INC_ISN, addr);
302         }
303     }
304
305     private void emmitJMP() {
306         Object o1 = operands.get(0);
307         if (o1 instanceof Token) {
308             Token t1 = (Token) o1;
309             if (Assembler.isIdent(t1)) {
310                 Label lab = (Label) labels.get(t1.image);
311                 lab = (lab == null) ? new Label(t1.image) : lab;
312                 stream.writeJMP(lab);
313             } else {
314                 System.out.println("unkown operand: " + t1.image);
315             }
316         } else {
317             System.out.println("unkown operand: " + o1);
318         }
319     }
320
321     private void emmitLEA() {
322         int addr = getAddressingMode(2);
323         switch (addr) {
324             case RI_ADDR:
325                 Indirect ind = getInd(1);
326                 stream.writeLEA(getReg(0), getRegister(ind.reg), ind.disp);
327                 break;
328             default:
329                 reportAddressingError(LEA_ISN, addr);
330         }
331     }
332
333     private void emmitMOV() {
334         int addr = getAddressingMode(2);
335         switch (addr) {
336             case RR_ADDR:
337                 stream.writeMOV(X86Constants.BITS32, getReg(0), getReg(1));
338                 break;
339             case RC_ADDR:
340                 stream.writeMOV_Const(getReg(0), getInt(1));
341                 break;
342             case RI_ADDR:
343                 Indirect ind = getInd(1);
344                 stream.writeMOV(X86Constants.BITS32, getReg(0), getRegister(ind.reg), ind.disp);
345                 break;
346             case IR_ADDR:
347                 ind = getInd(0);
348                 stream.writeMOV(X86Constants.BITS32, getRegister(ind.reg), ind.disp, getReg(1));
349                 break;
350             case IC_ADDR:
351                 ind = getInd(0);
352                 stream.writeMOV_Const(X86Constants.BITS32, getRegister(ind.reg), ind.disp, getInt(1));
353                 break;
354             default:
355                 reportAddressingError(MOV_ISN, addr);
356         }
357     }
358
359     private void emmitNOP() {
360         stream.writeNOP();
361     }
362
363     private void emmitOR() {
364         int addr = getAddressingMode(2);
365         switch (addr) {
366             case RR_ADDR:
367                 stream.writeOR(getReg(0), getReg(1));
368                 break;
369             case RC_ADDR:
370                 stream.writeOR(getReg(0), getInt(1));
371                 break;
372             case RI_ADDR:
373                 Indirect ind = getInd(1);
374                 stream.writeOR(getReg(0), getRegister(ind.reg), ind.disp);
375                 break;
376             case IR_ADDR:
377                 ind = getInd(0);
378                 stream.writeOR(getRegister(ind.reg), ind.disp, getReg(1));
379                 break;
380             case IC_ADDR:
381                 ind = getInd(0);
382                 stream.writeOR(X86Constants.BITS32, getRegister(ind.reg), ind.disp, getInt(1));
383                 break;
384             default:
385                 reportAddressingError(OR_ISN, addr);
386         }
387     }
388
389     private void emmitPOP() {
390         int addr = getAddressingMode(1);
391         switch (addr) {
392             case R_ADDR:
393                 stream.writePOP(getReg(0));
394                 break;
395             case I_ADDR:
396                 Indirect ind = getInd(0);
397                 stream.writePOP(getRegister(ind.reg), ind.disp);
398                 break;
399             default:
400                 reportAddressingError(POP_ISN, addr);
401         }
402     }
403
404     private void emmitPUSH() {
405         int addr = getAddressingMode(1);
406         switch (addr) {
407             case C_ADDR:
408                 stream.writePUSH(getInt(0));
409                 break;
410             case R_ADDR:
411                 stream.writePUSH(getReg(0));
412                 break;
413             case I_ADDR:
414                 Indirect ind = getInd(0);
415                 stream.writePUSH(getRegister(ind.reg), ind.disp);
416                 break;
417             default:
418                 reportAddressingError(PUSH_ISN, addr);
419         }
420     }
421
422     private void emmitRET() {
423         int addr = getAddressingMode(1);
424         switch (addr) {
425             case N_ADDR:
426                 stream.writeRET();
427                 break;
428             case C_ADDR:
429                 stream.writeRET(getInt(0));
430                 break;
431             default:
432                 reportAddressingError(RET_ISN, addr);
433         }
434     }
435
436     private void emmitSHR() {
437         int addr = getAddressingMode(2);
438         switch (addr) {
439             case RC_ADDR:
440                 stream.writeSHR(getReg(0), getInt(1));
441                 break;
442             case IC_ADDR:
443                 Indirect ind = getInd(0);
444                 stream.writeSHR(X86Constants.BITS32, getRegister(ind.reg), ind.disp, getInt(1));
445                 break;
446             default:
447                 reportAddressingError(SHR_ISN, addr);
448         }
449     }
450
451     private void emmitTEST() {
452         int addr = getAddressingMode(2);
453         switch (addr) {
454             case RR_ADDR:
455                 stream.writeTEST(getReg(0), getReg(1));
456                 break;
457             case RC_ADDR:
458                 stream.writeTEST(getReg(0), getInt(1));
459                 break;
460             case IC_ADDR:
461                 Indirect ind = getInd(0);
462                 stream.writeTEST(X86Constants.BITS32, getRegister(ind.reg), ind.disp, getInt(1));
463                 break;
464             default:
465                 reportAddressingError(TEST_ISN, addr);
466         }
467     }
468
469     private void emmitXCHG() {
470         int addr = getAddressingMode(2);
471         switch (addr) {
472             case RR_ADDR:
473                 stream.writeXCHG(getReg(0), getReg(1));
474                 break;
475             case IR_ADDR:
476                 Indirect ind = getInd(0);
477                 stream.writeXCHG(getRegister(ind.reg), ind.disp, getReg(1));
478                 break;
479             default:
480                 reportAddressingError(XCHG_ISN, addr);
481         }
482     }
483
484     private void emmitXOR() {
485         int addr = getAddressingMode(2);
486         switch (addr) {
487             case RR_ADDR:
488                 stream.writeXOR(getReg(0), getReg(1));
489                 break;
490             case RC_ADDR:
491                 stream.writeXOR(getReg(0), getInt(1));
492                 break;
493             case RI_ADDR:
494                 Indirect ind = getInd(1);
495                 stream.writeXOR(getReg(0), getRegister(ind.reg), ind.disp);
496                 break;
497             case IR_ADDR:
498                 ind = getInd(0);
499                 stream.writeXOR(getRegister(ind.reg), ind.disp, getReg(1));
500                 break;
501             case IC_ADDR:
502                 ind = getInd(0);
503                 stream.writeXOR(X86Constants.BITS32, getRegister(ind.reg), ind.disp, getInt(1));
504                 break;
505             default:
506                 reportAddressingError(XOR_ISN, addr);
507         }
508     }
509
510     private void reportAddressingError(int instruction, int addressing){
511         String err = "";
512         int ad = addressing;
513         do {
514             err += " " + ARG_TYPES[ad & 3];
515             ad >>= DISP;
516         } while(ad != 0);
517
518         System.out.println("Unkown addressing mode (" + err + " ) for " + MNEMONICS[instruction]);
519     }
520
521     static final X86Register.GPR getRegister(Token t) {
522         try {
523             return X86Register.getGPR(t.image);
524         } catch (IllegalArgumentException x) {
525             System.err.println(x.getMessage());
526             return X86Register.EAX;
527         }
528     }
529 }