001/*
002 *  This file is part of the Jikes RVM project (http://jikesrvm.org).
003 *
004 *  This file is licensed to You under the Eclipse Public License (EPL);
005 *  You may not use this file except in compliance with the License. You
006 *  may obtain a copy of the License at
007 *
008 *      http://www.opensource.org/licenses/eclipse-1.0.php
009 *
010 *  See the COPYRIGHT.txt file distributed with this work for information
011 *  regarding copyright ownership.
012 */
013package org.jikesrvm.compilers.common.assembler.ia32;
014
015import org.jikesrvm.VM;
016import org.jikesrvm.architecture.MachineRegister;
017import org.vmmagic.unboxed.Offset;
018import org.vmmagic.unboxed.Address;
019import org.vmmagic.pragma.Pure;
020
021/**
022 */
023public final class Lister {
024
025  private static final int PREFIX_AREA_SIZE = 8;
026  private static final int OP_AREA_SIZE = 9;
027  private static final int SOURCE_AREA_SIZE = 16;
028  private static final int DEST_AREA_SIZE = 16;
029
030  private final Assembler asm;
031
032  private enum Prefix {LOCK, LIKELY, UNLIKELY};
033
034  private Prefix prefix;
035
036  public Lister(Assembler asm) {
037    this.asm = asm;
038  }
039
040  public void lockPrefix() {
041    prefix = Prefix.LOCK;
042  }
043
044  public void branchLikelyPrefix() {
045    prefix = Prefix.LIKELY;
046  }
047
048  public void branchUnlikelyPrefix() {
049    prefix = Prefix.UNLIKELY;
050  }
051
052  public void OP(int i, String op) {
053    i = begin(i, op);
054    VM.sysWrite(right("", DEST_AREA_SIZE));
055    VM.sysWrite(right("", SOURCE_AREA_SIZE));
056    end(i);
057  }
058
059  public void I(int i, String op, int n) {
060    i = begin(i, op);
061    VM.sysWrite(right(decimal(n) + " ", DEST_AREA_SIZE));
062    VM.sysWrite(right("", SOURCE_AREA_SIZE));
063    end(i);
064  }
065
066  public void R(int i, String op, MachineRegister R0) {
067    i = begin(i, op);
068    VM.sysWrite(right(R0 + " ", DEST_AREA_SIZE));
069    VM.sysWrite(right("", SOURCE_AREA_SIZE));
070    end(i);
071  }
072
073  public void RD(int i, String op, MachineRegister R0, Offset d) {
074    i = begin(i, op);
075    VM.sysWrite(right(decimal(d) + "[" + R0 + "]", DEST_AREA_SIZE));
076    VM.sysWrite(right("", SOURCE_AREA_SIZE));
077    end(i);
078  }
079
080  public void RI(int i, String op, MachineRegister R0, long n) {
081    i = begin(i, op);
082    VM.sysWrite(right(R0 + " ", DEST_AREA_SIZE));
083    VM.sysWrite(right(decimal(n) + " ", SOURCE_AREA_SIZE));
084    end(i);
085  }
086
087  public void RDI(int i, String op, MachineRegister R0, Offset d, long n) {
088    i = begin(i, op);
089    VM.sysWrite(right(decimal(d) + "[" + R0 + "]", DEST_AREA_SIZE));
090    VM.sysWrite(right(decimal(n) + " ", SOURCE_AREA_SIZE));
091    end(i);
092  }
093
094  public void RNI(int i, String op, MachineRegister R0, long n) {
095    i = begin(i, op);
096    VM.sysWrite(right("[" + R0 + "]", DEST_AREA_SIZE));
097    VM.sysWrite(right(decimal(n) + " ", SOURCE_AREA_SIZE));
098    end(i);
099  }
100
101  public void RR(int i, String op, MachineRegister R0, MachineRegister R1) {
102    i = begin(i, op);
103    VM.sysWrite(right(R0 + " ", DEST_AREA_SIZE));
104    VM.sysWrite(right(R1 + " ", SOURCE_AREA_SIZE));
105    end(i);
106  }
107
108  public void RDR(int i, String op, MachineRegister R0, Offset d, MachineRegister R1) {
109    i = begin(i, op);
110    VM.sysWrite(right(decimal(d) + "[" + R0 + "]", DEST_AREA_SIZE));
111    VM.sysWrite(right(R1 + " ", SOURCE_AREA_SIZE));
112    end(i);
113  }
114
115  public void RDRI(int i, String op, MachineRegister R0, Offset d, MachineRegister R1, int imm) {
116    i = begin(i, op);
117    VM.sysWrite(right(decimal(d) + "[" + R0 + "]", DEST_AREA_SIZE));
118    VM.sysWrite(right(R1 + " ", SOURCE_AREA_SIZE));
119    VM.sysWrite(right(decimal(imm), SOURCE_AREA_SIZE));
120    end(i);
121  }
122
123  public void RDRR(int i, String op, MachineRegister R0, Offset d, MachineRegister R1, MachineRegister R2) {
124    i = begin(i, op);
125    VM.sysWrite(right(decimal(d) + "[" + R0 + "]", DEST_AREA_SIZE));
126    VM.sysWrite(right(R1 + " ", SOURCE_AREA_SIZE));
127    VM.sysWrite(right(R2 + " ", SOURCE_AREA_SIZE));
128    end(i);
129  }
130
131  public void RRD(int i, String op, MachineRegister R0, MachineRegister R1, Offset d) {
132    i = begin(i, op);
133    VM.sysWrite(right(R0 + " ", DEST_AREA_SIZE));
134    VM.sysWrite(right(decimal(d) + "[" + R1 + "]", SOURCE_AREA_SIZE));
135    end(i);
136  }
137
138  public void RNR(int i, String op, MachineRegister R0, MachineRegister R1) {
139    i = begin(i, op);
140    VM.sysWrite(right("[" + R0 + "]", DEST_AREA_SIZE));
141    VM.sysWrite(right(R1 + " ", SOURCE_AREA_SIZE));
142    end(i);
143  }
144
145  public void RN(int i, String op, MachineRegister R0) {
146    i = begin(i, op);
147    VM.sysWrite(right("[" + R0 + "]", DEST_AREA_SIZE));
148    VM.sysWrite(right(" ", SOURCE_AREA_SIZE));
149    end(i);
150  }
151
152  public void RRN(int i, String op, MachineRegister R0, MachineRegister R1) {
153    i = begin(i, op);
154    VM.sysWrite(right(R0 + " ", DEST_AREA_SIZE));
155    VM.sysWrite(right("[" + R1 + "]", SOURCE_AREA_SIZE));
156    end(i);
157  }
158
159  public void RXD(int i, String op, MachineRegister R0, MachineRegister X, short s, Offset d) {
160    i = begin(i, op);
161    VM.sysWrite(right("[" + decimal(d) + "+" + R0 + "+" + X + "<<" + decimal(s) + "]",
162                      DEST_AREA_SIZE));
163    VM.sysWrite(right("", SOURCE_AREA_SIZE));
164    end(i);
165  }
166
167  public void RXDI(int i, String op, MachineRegister R0, MachineRegister X, short s, Offset d, long n) {
168    i = begin(i, op);
169    VM.sysWrite(right("[" + decimal(d) + "+" + R0 + "+" + X + "<<" + decimal(s) + "]",
170                      DEST_AREA_SIZE));
171    VM.sysWrite(right(decimal(n), SOURCE_AREA_SIZE));
172    end(i);
173  }
174
175  public void RFD(int i, String op, MachineRegister X, short s, Offset d) {
176    i = begin(i, op);
177    VM.sysWrite(right("[" + decimal(d) + "+" + X + "<<" + decimal(s) + "]", DEST_AREA_SIZE));
178    VM.sysWrite(right("", SOURCE_AREA_SIZE));
179    end(i);
180  }
181
182  public void RA(int i, String op, Address d) {
183    i = begin(i, op);
184    VM.sysWrite(right("[" + hex(d) + "]", DEST_AREA_SIZE));
185    VM.sysWrite(right("", SOURCE_AREA_SIZE));
186    end(i);
187  }
188
189  public void RFDI(int i, String op, MachineRegister X, short s, Offset d, long n) {
190    i = begin(i, op);
191    VM.sysWrite(right("[" + decimal(d) + "+" + X + "<<" + decimal(s) + "]", DEST_AREA_SIZE));
192    VM.sysWrite(right(decimal(n), SOURCE_AREA_SIZE));
193    end(i);
194  }
195
196  public void RAI(int i, String op, Address d, long n) {
197    i = begin(i, op);
198    VM.sysWrite(right("[" + hex(d) + "]", DEST_AREA_SIZE));
199    VM.sysWrite(right(decimal(n), SOURCE_AREA_SIZE));
200    end(i);
201  }
202
203  public void RRR(int i, String op, MachineRegister R0, MachineRegister R1, MachineRegister R2) {
204    i = begin(i, op);
205    VM.sysWrite(right(R0 + " ", DEST_AREA_SIZE));
206    VM.sysWrite(right(R1 + " ", SOURCE_AREA_SIZE));
207    VM.sysWrite(right(R2 + " ", SOURCE_AREA_SIZE));
208    end(i);
209  }
210
211  public void RNRI(int i, String op, MachineRegister R0, MachineRegister R1, int imm) {
212    i = begin(i, op);
213    VM.sysWrite(right("[" + R0 + "] ", DEST_AREA_SIZE));
214    VM.sysWrite(right(R1 + " ", SOURCE_AREA_SIZE));
215    VM.sysWrite(right(decimal(imm), SOURCE_AREA_SIZE));
216    end(i);
217  }
218
219  public void RNRR(int i, String op, MachineRegister R0, MachineRegister R1, MachineRegister R2) {
220    i = begin(i, op);
221    VM.sysWrite(right("[" + R0 + "] ", DEST_AREA_SIZE));
222    VM.sysWrite(right(R1 + " ", SOURCE_AREA_SIZE));
223    VM.sysWrite(right(R2 + " ", SOURCE_AREA_SIZE));
224    end(i);
225  }
226
227  public void RRI(int i, String op, MachineRegister R0, MachineRegister R1, int imm) {
228    i = begin(i, op);
229    VM.sysWrite(right(R0 + " ", DEST_AREA_SIZE));
230    VM.sysWrite(right(R1 + " ", SOURCE_AREA_SIZE));
231    VM.sysWrite(right(decimal(imm), SOURCE_AREA_SIZE));
232    end(i);
233  }
234
235  public void RRXD(int i, String op, MachineRegister R0, MachineRegister R1, MachineRegister X, short s, Offset d) {
236    i = begin(i, op);
237    VM.sysWrite(right(R0 + " ", DEST_AREA_SIZE));
238    VM.sysWrite(right("[" + decimal(d) + "+" + R1 + "+" + X + "<<" + decimal(s) + "]",
239                      SOURCE_AREA_SIZE));
240    end(i);
241  }
242
243  public void RXDR(int i, String op, MachineRegister R0, MachineRegister X, short s, Offset d, MachineRegister R1) {
244    i = begin(i, op);
245    VM.sysWrite(right("[" + decimal(d) + "+" + R0 + "+" + X + "<<" + decimal(s) + "]",
246                      DEST_AREA_SIZE));
247    VM.sysWrite(right(R1 + " ", SOURCE_AREA_SIZE));
248    end(i);
249  }
250
251  public void RXDRI(int i, String op, MachineRegister R0, MachineRegister X, short s, Offset d, MachineRegister R1, int imm) {
252    i = begin(i, op);
253    VM.sysWrite(right("[" + decimal(d) + "+" + R0 + "+" + X + "<<" + decimal(s) + "]",
254                      DEST_AREA_SIZE));
255    VM.sysWrite(right(R1 + " ", SOURCE_AREA_SIZE));
256    VM.sysWrite(right(decimal(imm), SOURCE_AREA_SIZE));
257    end(i);
258  }
259
260  public void RXDRR(int i, String op, MachineRegister R0, MachineRegister X, short s, Offset d, MachineRegister R1, MachineRegister R2) {
261    i = begin(i, op);
262    VM.sysWrite(right("[" + decimal(d) + "+" + R0 + "+" + X + "<<" + decimal(s) + "]",
263                      SOURCE_AREA_SIZE));
264    VM.sysWrite(right(R1 + " ", DEST_AREA_SIZE));
265    VM.sysWrite(right(R2 + " ", SOURCE_AREA_SIZE));
266    end(i);
267  }
268
269  public void RRFD(int i, String op, MachineRegister R0, MachineRegister X, short s, Offset d) {
270    i = begin(i, op);
271    VM.sysWrite(right(R0 + " ", DEST_AREA_SIZE));
272    VM.sysWrite(right("[" + decimal(d) + "+" + X + "<<" + decimal(s) + "]", SOURCE_AREA_SIZE));
273    end(i);
274  }
275
276  public void RFDR(int i, String op, MachineRegister X, short s, Offset d, MachineRegister R0) {
277    i = begin(i, op);
278    VM.sysWrite(right(R0 + " ", DEST_AREA_SIZE));
279    VM.sysWrite(right("[" + decimal(d) + "+" + X + "<<" + decimal(s) + "]", SOURCE_AREA_SIZE));
280    end(i);
281  }
282
283  public void RFDRI(int i, String op, MachineRegister X, short s, Offset d, MachineRegister R0, int imm) {
284    i = begin(i, op);
285    VM.sysWrite(right(R0 + " ", DEST_AREA_SIZE));
286    VM.sysWrite(right("[" + decimal(d) + "+" + X + "<<" + decimal(s) + "]", SOURCE_AREA_SIZE));
287    VM.sysWrite(right(decimal(imm), SOURCE_AREA_SIZE));
288    end(i);
289  }
290
291  public void RFDRR(int i, String op, MachineRegister X, short s, Offset d, MachineRegister R0, MachineRegister R2) {
292    i = begin(i, op);
293    VM.sysWrite(right(R0 + " ", DEST_AREA_SIZE));
294    VM.sysWrite(right("[" + decimal(d) + "+" + X + "<<" + decimal(s) + "]", SOURCE_AREA_SIZE));
295    VM.sysWrite(right(R2 + " ", SOURCE_AREA_SIZE));
296    end(i);
297  }
298
299  public void RRA(int i, String op, MachineRegister R0, Address d) {
300    i = begin(i, op);
301    VM.sysWrite(right(R0 + " ", DEST_AREA_SIZE));
302    VM.sysWrite(right("[" + hex(d) + "]", SOURCE_AREA_SIZE));
303    end(i);
304  }
305
306  public void RAR(int i, String op, Address d, MachineRegister R0) {
307    i = begin(i, op);
308    VM.sysWrite(right(R0 + " ", DEST_AREA_SIZE));
309    VM.sysWrite(right("[" + hex(d) + "]", SOURCE_AREA_SIZE));
310    end(i);
311  }
312
313  public void RARI(int i, String op, Address d, MachineRegister R0, int imm) {
314    i = begin(i, op);
315    VM.sysWrite(right(R0 + " ", DEST_AREA_SIZE));
316    VM.sysWrite(right("[" + hex(d) + "]", SOURCE_AREA_SIZE));
317    VM.sysWrite(right(decimal(imm), SOURCE_AREA_SIZE));
318    end(i);
319  }
320
321  public void RARR(int i, String op, Address d, MachineRegister R0, MachineRegister R2) {
322    i = begin(i, op);
323    VM.sysWrite(right(R0 + " ", DEST_AREA_SIZE));
324    VM.sysWrite(right("[" + hex(d) + "]", SOURCE_AREA_SIZE));
325    VM.sysWrite(right(R2 + " ", SOURCE_AREA_SIZE));
326    end(i);
327  }
328
329  private int begin(int i, String op) {
330    if (prefix != null) i--;
331    VM.sysWrite(right(hex(i), 6) + "| ");
332    if (prefix != null) {
333      VM.sysWrite(right(prefix.toString(), PREFIX_AREA_SIZE) + " ");
334    } else {
335      VM.sysWrite(right("", PREFIX_AREA_SIZE) + " ");
336    }
337    VM.sysWrite(left(op, OP_AREA_SIZE));
338    return i;
339  }
340
341  private void end(int i) {
342    VM.sysWrite(" | ");
343    asm.writeLastInstruction(i);
344    VM.sysWrite("\n");
345    prefix = null;
346  }
347
348  @Pure
349  private static String left(String s, int w) {
350    int n = s.length();
351    if (w < n) return s.substring(0, w);
352    StringBuilder result = new StringBuilder(s);
353    for (int i = n; i < w; i++) {
354      result.append(' ');
355    }
356    return result.toString();
357  }
358
359  @Pure
360  private static String right(String s, int w) {
361    int n = s.length();
362    if (w < n) return s.substring(n - w);
363    StringBuilder result = new StringBuilder();
364    for (int i = n; i < w; i++) {
365      result.append(' ');
366    }
367    result.append(s);
368    return result.toString();
369  }
370
371  private static String decimal(Offset o) {
372    return decimal(o.toInt());
373  }
374
375  @Pure
376  static String decimal(int n) {
377    if (n == 0) return "0";
378    String sign = "";
379    if (n < 0) {
380      sign = "-";
381      n = -n;
382    }
383    String result = "";
384    while (0 < n) {
385      int i = n % 10;
386      n /= 10;
387      if (i == 0) {
388        result = "0" + result;
389      } else if (i == 1) {
390        result = "1" + result;
391      } else if (i == 2) {
392        result = "2" + result;
393      } else if (i == 3) {
394        result = "3" + result;
395      } else if (i == 4) {
396        result = "4" + result;
397      } else if (i == 5) {
398        result = "5" + result;
399      } else if (i == 6) {
400        result = "6" + result;
401      } else if (i == 7) {
402        result = "7" + result;
403      } else if (i == 8) {
404        result = "8" + result;
405      } else if (i == 9) result = "9" + result;
406    }
407    return (sign + result);
408  }
409
410  @Pure
411  static String decimal(long n) {
412    if (n == 0) return "0";
413    String sign = "";
414    if (n < 0) {
415      sign = "-";
416      n = -n;
417    }
418    String result = "";
419    while (0 < n) {
420      long i = n % 10;
421      n /= 10;
422      if (i == 0) {
423        result = "0" + result;
424      } else if (i == 1) {
425        result = "1" + result;
426      } else if (i == 2) {
427        result = "2" + result;
428      } else if (i == 3) {
429        result = "3" + result;
430      } else if (i == 4) {
431        result = "4" + result;
432      } else if (i == 5) {
433        result = "5" + result;
434      } else if (i == 6) {
435        result = "6" + result;
436      } else if (i == 7) {
437        result = "7" + result;
438      } else if (i == 8) {
439        result = "8" + result;
440      } else if (i == 9) result = "9" + result;
441    }
442    return (sign + result);
443  }
444
445  private static String decimal(short s) {
446    return decimal((int) s);
447  }
448
449  @Pure
450  static String hex(Address i) {
451    return (hex((short) (i.toInt() >> 16)) + hex((short) i.toWord().toInt()));
452  }
453
454  @Pure
455  public static String hex(int i) {
456    return (hex((short) (i >> 16)) + hex((short) i));
457  }
458
459  @Pure
460  static String hex(short i) {
461    return (hex((byte) (i >> 8)) + hex((byte) i));
462  }
463
464  @Pure
465  static String hex(byte b) {
466    int i = b & 0xFF;
467    byte j = (byte) (i / 0x10);
468    String s;
469    if (j == 0x0) {
470      s = "0";
471    } else if (j == 0x1) {
472      s = "1";
473    } else if (j == 0x2) {
474      s = "2";
475    } else if (j == 0x3) {
476      s = "3";
477    } else if (j == 0x4) {
478      s = "4";
479    } else if (j == 0x5) {
480      s = "5";
481    } else if (j == 0x6) {
482      s = "6";
483    } else if (j == 0x7) {
484      s = "7";
485    } else if (j == 0x8) {
486      s = "8";
487    } else if (j == 0x9) {
488      s = "9";
489    } else if (j == 0xA) {
490      s = "A";
491    } else if (j == 0xB) {
492      s = "B";
493    } else if (j == 0xC) {
494      s = "C";
495    } else if (j == 0xD) {
496      s = "D";
497    } else if (j == 0xE) {
498      s = "E";
499    } else {
500      s = "F";
501    }
502    j = (byte) (i % 0x10);
503    String t;
504    if (j == 0x0) {
505      t = "0";
506    } else if (j == 0x1) {
507      t = "1";
508    } else if (j == 0x2) {
509      t = "2";
510    } else if (j == 0x3) {
511      t = "3";
512    } else if (j == 0x4) {
513      t = "4";
514    } else if (j == 0x5) {
515      t = "5";
516    } else if (j == 0x6) {
517      t = "6";
518    } else if (j == 0x7) {
519      t = "7";
520    } else if (j == 0x8) {
521      t = "8";
522    } else if (j == 0x9) {
523      t = "9";
524    } else if (j == 0xA) {
525      t = "A";
526    } else if (j == 0xB) {
527      t = "B";
528    } else if (j == 0xC) {
529      t = "C";
530    } else if (j == 0xD) {
531      t = "D";
532    } else if (j == 0xE) {
533      t = "E";
534    } else {
535      t = "F";
536    }
537    return s + t;
538  }
539
540  public void noteBytecode(int i, String bcode) {
541    VM.sysWrite("[" + decimal(i) + "] " + bcode + "\n");
542  }
543
544  public void comment(int i, String comment) {
545    VM.sysWrite(right(hex(i), 6) + "| " + comment + "\n");
546  }
547
548  public void comefrom(int i, int j) {
549    VM.sysWrite(right(hex(i), 6) + "| <<< " + right(hex(j), 6) + "\n");
550  }
551}