JNAsm implementation in progress.
[jnode:svn-mirror.git] / builder / src / builder / org / jnode / jnasm / assembler / Assembler.java
1 /**
2  * $Id$  
3  */
4 package org.jnode.jnasm.assembler;
5
6 import org.jnode.jnasm.assembler.x86.X86Support;
7
8 import java.util.ArrayList;
9 import java.util.List;
10 import java.util.Map;
11 import java.util.HashMap;
12 import java.io.FileOutputStream;
13 import java.io.IOException;
14 import java.io.Reader;
15 import java.io.InputStream;
16 import java.io.OutputStream;
17 import java.io.StringReader;
18 import java.io.StringWriter;
19 import java.io.InputStreamReader;
20
21 /**
22  * @author Levente S\u00e1ntha
23  */
24 public abstract class Assembler {
25     public static final boolean THROW = false;
26     protected static final Object UNDEFINED = new String("UNDEFIEND");
27     final List instructions = new ArrayList();
28     private final Map constants = new HashMap();
29     private final Map labels = new HashMap();
30     private int pass = 0;
31     private final HardwareSupport hwSupport;
32     private final PseudoInstructions pseudo;
33
34     public static void main(String[] argv) throws Exception {
35         Assembler jnasm = newInstance(System.in);
36         FileOutputStream out = new FileOutputStream("out");
37         jnasm.performTwoPasses(new InputStreamReader(System.in), out);
38         out.flush();
39         out.close();
40     }
41
42     protected Assembler() {
43         pseudo = new PseudoInstructions(labels);
44         hwSupport = new X86Support(this, instructions, labels);
45     }
46
47     public PseudoInstructions getPseudo() {
48         return pseudo;
49     }
50
51     public void performTwoPasses(Reader reader, OutputStream out) throws Exception{
52         StringWriter sw = new StringWriter();
53         char[] buf = new char[1024];
54         for(int count; (count = reader.read(buf)) > -1; sw.write(buf, 0, count));
55         sw.flush();
56         sw.close();
57         String data = sw.toString();
58
59         //1st pass
60         ReInit(new StringReader(data));
61         setPass(1);
62         jnasmInput();
63         assemble();
64
65         //2nd pass
66         setPass(2);
67         instructions.clear();
68         ReInit(new StringReader(data));
69         jnasmInput();
70         emmit(out);
71     }
72
73     public void assemble() {
74         hwSupport.assemble();
75     }
76
77     public void setPass(int pass) {
78         this.pass = pass;
79         hwSupport.setPass(pass);
80     }
81
82     public abstract void jnasmInput() throws ParseException;
83
84     public abstract void ReInit(Reader stream);
85
86     public static Assembler newInstance(InputStream in) {
87         return new JNAsm(in);
88     }
89
90     public static Assembler newInstance(Reader reader) {
91         return new JNAsm(reader);
92     }
93
94     public void emmit(OutputStream out) throws IOException{
95         assemble();
96         hwSupport.writeTo(out);
97     }
98
99     public static final boolean isIdent(Token t) {
100         return t.kind == JNAsmConstants.IDENT || t.kind == JNAsmConstants.REGISTER;
101     }
102
103     static final boolean isNumber(Token t) {
104         int k = t.kind;
105         return k == JNAsmConstants.DECNUMBER ||
106                 k == JNAsmConstants.BINNUMBER ||
107                 k == JNAsmConstants.OCTNUMBER ||
108                 k == JNAsmConstants.HEXNUMBER;
109     }
110
111     static final int getNumber(Token t) {
112         int ret;
113         String s = t.image;
114         try {
115             switch (t.kind) {
116                 case JNAsmConstants.DECNUMBER:
117                     ret = Integer.parseInt(s);
118                     break;
119
120                 case JNAsmConstants.BINNUMBER:
121                     ret = Integer.parseInt(s.substring(0, s.length() - 1), 2);
122                     break;
123
124                 case JNAsmConstants.OCTNUMBER:
125                     ret = Integer.parseInt(s.substring(0, s.length() - 1), 8);
126                     break;
127
128                 case JNAsmConstants.HEXNUMBER:
129                     if (s.endsWith("h") || s.endsWith("H")) {
130                         ret = Integer.parseInt(s.substring(0, s.length() - 1), 16);
131                     } else {
132                         ret = Integer.parseInt(s.substring(2), 16);
133                     }
134                     break;
135
136                 default:
137                     throw new IllegalArgumentException("Unkown number type: " + t.kind);
138
139             }
140         } catch (RuntimeException x) {
141             if (THROW) {
142                 throw x;
143             } else {
144                 //x.printStackTrace();
145                 System.err.println("Invaid int: " + x.getMessage());
146                 return 0;
147             }
148         }
149         return ret;
150     }
151
152     public void putConstant(String name, int value) {
153         if (constants.get(name) != null && pass == 1)
154             throw new IllegalArgumentException("Constant already defined: " + name);
155
156         constants.put(name, new Integer(value));
157     }
158
159     int getConstant(String name) {
160         Integer i = (Integer) constants.get(name);
161         try {
162             if (i == null)
163                 throw new IllegalArgumentException("Undefined constant: " + name);
164         } catch (RuntimeException x) {
165             if (THROW) {
166                 throw x;
167             } else {
168                 //x.printStackTrace();
169                 if(pass == 2) System.err.println(x.getMessage());
170                 return 0;
171             }
172         }
173         return i.intValue();
174     }
175 }