OpenCores
URL https://opencores.org/ocsvn/lxp32/lxp32/trunk

Subversion Repositories lxp32

[/] [lxp32/] [trunk/] [tools/] [src/] [lxp32asm/] [main.cpp] - Blame information for rev 2

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 ring0_mipt
/*
2
 * Copyright (c) 2016 by Alex I. Kuznetsov.
3
 *
4
 * Part of the LXP32 CPU IP core.
5
 *
6
 * Main translation unit for the LXP32 assembler/linker.
7
 */
8
 
9
#include "assembler.h"
10
#include "linker.h"
11
 
12
#include <iostream>
13
#include <fstream>
14
#include <vector>
15
#include <string>
16
#include <exception>
17
#include <utility>
18
#include <memory>
19
#include <cstdlib>
20
#include <cstring>
21
#include <cassert>
22
 
23
struct Options {
24
        enum OutputFormat {Bin,Textio,Dec,Hex};
25
 
26
        bool compileOnly=false;
27
        std::string outputFileName;
28
        std::vector<std::string> includeSearchDirs;
29
        LinkableObject::Word base=0;
30
        std::size_t align=4;
31
        std::size_t imageSize=0;
32
        OutputFormat fmt=Bin;
33
};
34
 
35
static void displayUsage(std::ostream &os,const char *program) {
36
        os<<std::endl;
37
        os<<"Usage:"<<std::endl;
38
        os<<"    "<<program<<" [ option(s) | input file(s) ]"<<std::endl<<std::endl;
39
 
40
        os<<"Options:"<<std::endl;
41
        os<<"    -a <align>   Section alignment (default: 4)"<<std::endl;
42
        os<<"    -b <addr>    Base address (default: 0)"<<std::endl;
43
        os<<"    -c           Compile only (don't link)"<<std::endl;
44
        os<<"    -f <fmt>     Output file format (see below)"<<std::endl;
45
        os<<"    -h, --help   Display a short help message"<<std::endl;
46
        os<<"    -i <dir>     Add directory to the list of directories used to search"<<std::endl;
47
        os<<"                 for included files (multiple directories can be specified)"<<std::endl;
48
        os<<"    -o <file>    Output file name"<<std::endl;
49
        os<<"    -s <size>    Output image size"<<std::endl;
50
        os<<"    --           Do not interpret subsequent arguments as options"<<std::endl;
51
        os<<std::endl;
52
        os<<"Section alignment and image size must be multiples of 4."<<std::endl;
53
        os<<"Base address must be a multiple of section alignment."<<std::endl;
54
        os<<std::endl;
55
 
56
        os<<"Output file formats:"<<std::endl;
57
        os<<"    bin          Raw binary image (default)"<<std::endl;
58
        os<<"    textio       Text representation of binary data. Supported by"<<std::endl;
59
        os<<"                 std.textio (VHDL) and $readmemb (Verilog)"<<std::endl;
60
        os<<"    dec          Text format, one word per line (decimal)"<<std::endl;
61
        os<<"    hex          Text format, one word per line (hexadecimal)"<<std::endl;
62
}
63
 
64
static bool isLinkableObject(const std::string &filename) {
65
        static const char *id="LinkableObject";
66
        static std::size_t idSize=std::strlen(id);
67
 
68
        std::ifstream in(filename,std::ios_base::in);
69
        if(!in) return false;
70
 
71
        std::vector<char> buf(idSize);
72
        in.read(buf.data(),idSize);
73
        if(static_cast<std::size_t>(in.gcount())!=idSize) return false;
74
        if(std::memcmp(buf.data(),id,idSize)) return false;
75
        return true;
76
}
77
 
78
int main(int argc,char *argv[]) try {
79
        std::vector<std::string> inputFiles;
80
        Options options;
81
        bool alignmentSpecified=false;
82
        bool baseSpecified=false;
83
        bool formatSpecified=false;
84
        bool noMoreOptions=false;
85
 
86
        std::cout<<"LXP32 Platform Assembler and Linker"<<std::endl;
87
        std::cout<<"Copyright (c) 2016 by Alex I. Kuznetsov"<<std::endl;
88
 
89
        if(argc<=1) {
90
                displayUsage(std::cout,argv[0]);
91
                return 0;
92
        }
93
 
94
        for(int i=1;i<argc;i++) {
95
                if(argv[i][0]!='-'||noMoreOptions) inputFiles.push_back(argv[i]);
96
                else if(!strcmp(argv[i],"--")) noMoreOptions=true;
97
                else if(!strcmp(argv[i],"-a")) {
98
                        if(++i==argc) {
99
                                displayUsage(std::cerr,argv[0]);
100
                                return EXIT_FAILURE;
101
                        }
102
                        try {
103
                                options.align=std::stoul(argv[i],nullptr,0);
104
                                if(options.align%4!=0||options.align==0) throw std::exception();
105
                                alignmentSpecified=true;
106
                        }
107
                        catch(std::exception &) {
108
                                throw std::runtime_error("Invalid section alignment");
109
                        }
110
                }
111
                else if(!strcmp(argv[i],"-b")) {
112
                        if(++i==argc) {
113
                                displayUsage(std::cerr,argv[0]);
114
                                return EXIT_FAILURE;
115
                        }
116
                        try {
117
                                options.base=std::stoul(argv[i],nullptr,0);
118
                                //if(options.base%4!=0) throw std::exception();
119
                                baseSpecified=true;
120
                        }
121
                        catch(std::exception &) {
122
                                throw std::runtime_error("Invalid base address");
123
                        }
124
                }
125
                else if(!strcmp(argv[i],"-c")) {
126
                        options.compileOnly=true;
127
                }
128
                else if(!strcmp(argv[i],"-f")) {
129
                        if(++i==argc) {
130
                                displayUsage(std::cerr,argv[0]);
131
                                return EXIT_FAILURE;
132
                        }
133
                        if(!strcmp(argv[i],"bin")) options.fmt=Options::Bin;
134
                        else if(!strcmp(argv[i],"textio")) options.fmt=Options::Textio;
135
                        else if(!strcmp(argv[i],"dec")) options.fmt=Options::Dec;
136
                        else if(!strcmp(argv[i],"hex")) options.fmt=Options::Hex;
137
                        else throw std::runtime_error("Unrecognized output format");
138
                        formatSpecified=true;
139
                }
140
                else if(!strcmp(argv[i],"-h")||!strcmp(argv[i],"--help")) {
141
                        displayUsage(std::cout,argv[0]);
142
                        return 0;
143
                }
144
                else if(!strcmp(argv[i],"-i")) {
145
                        if(++i==argc) {
146
                                displayUsage(std::cerr,argv[0]);
147
                                return EXIT_FAILURE;
148
                        }
149
                        options.includeSearchDirs.push_back(argv[i]);
150
                }
151
                else if(!strcmp(argv[i],"-o")) {
152
                        if(++i==argc) {
153
                                displayUsage(std::cerr,argv[0]);
154
                                return EXIT_FAILURE;
155
                        }
156
                        options.outputFileName=argv[i];
157
                }
158
                else if(!strcmp(argv[i],"-s")) {
159
                        if(++i==argc) {
160
                                displayUsage(std::cerr,argv[0]);
161
                                return EXIT_FAILURE;
162
                        }
163
                        try {
164
                                options.imageSize=std::stoul(argv[i],nullptr,0);
165
                                if(options.imageSize%4!=0||options.imageSize==0) throw std::exception();
166
                        }
167
                        catch(std::exception &) {
168
                                throw std::runtime_error("Invalid image size");
169
                        }
170
                }
171
                else throw std::runtime_error(std::string("Unrecognized option: \"")+argv[i]+"\"");
172
        }
173
 
174
        if(options.base%options.align!=0)
175
                throw std::runtime_error("Base address must be a multiple of section alignment");
176
 
177
        if(options.compileOnly) {
178
                if(alignmentSpecified)
179
                        std::cerr<<"Warning: Section alignment is ignored in compile-only mode"<<std::endl;
180
                if(baseSpecified)
181
                        std::cerr<<"Warning: Base address is ignored in compile-only mode"<<std::endl;
182
                if(formatSpecified)
183
                        std::cerr<<"Warning: Output format is ignored in compile-only mode"<<std::endl;
184
                if(options.imageSize>0)
185
                        std::cerr<<"Warning: Image size is ignored in compile-only mode"<<std::endl;
186
        }
187
 
188
        if(inputFiles.empty())
189
                throw std::runtime_error("No input files were specified");
190
 
191
        if(options.compileOnly&&inputFiles.size()>1&&!options.outputFileName.empty())
192
                throw std::runtime_error("Output file name cannot be specified "
193
                        "for multiple files in compile-only mode");
194
 
195
        std::vector<Assembler> assemblers;
196
        std::vector<LinkableObject> rawObjects;
197
 
198
        for(auto const &filename: inputFiles) {
199
                if(options.compileOnly||!isLinkableObject(filename)) {
200
                        Assembler as;
201
                        for(auto const &dir: options.includeSearchDirs) as.addIncludeSearchDir(dir);
202
                        try {
203
                                as.processFile(filename);
204
                        }
205
                        catch(std::exception &ex) {
206
                                std::cerr<<"Assembler error in "<<as.currentFileName();
207
                                if(as.line()>0) std::cerr<<":"<<as.line();
208
                                std::cerr<<": "<<ex.what()<<std::endl;
209
                                return EXIT_FAILURE;
210
                        }
211
                        if(!options.compileOnly) assemblers.push_back(std::move(as));
212
                        else {
213
                                std::string outputFileName=options.outputFileName;
214
                                if(outputFileName.empty()) {
215
                                        outputFileName=filename;
216
                                        auto pos=outputFileName.find_last_of('.');
217
                                        if(pos!=std::string::npos) outputFileName.erase(pos);
218
                                        outputFileName+=".lo";
219
                                }
220
                                as.object().serialize(outputFileName);
221
                        }
222
                }
223
                else {
224
                        LinkableObject lo;
225
                        try {
226
                                lo.deserialize(filename);
227
                        }
228
                        catch(std::exception &ex) {
229
                                std::cerr<<"Error reading object file "<<filename<<": "<<ex.what()<<std::endl;
230
                                return EXIT_FAILURE;
231
                        }
232
                        rawObjects.push_back(std::move(lo));
233
                }
234
        }
235
 
236
        if(options.compileOnly) return 0;
237
 
238
        Linker linker;
239
        for(auto &lo: rawObjects) linker.addObject(lo);
240
        for(auto &as: assemblers) linker.addObject(as.object());
241
        linker.setBase(options.base);
242
        linker.setAlignment(options.align);
243
        linker.setImageSize(options.imageSize);
244
 
245
        std::string outputFileName=options.outputFileName;
246
        if(outputFileName.empty()) {
247
                outputFileName=inputFiles[0];
248
                auto pos=outputFileName.find_last_of('.');
249
                if(pos!=std::string::npos) outputFileName.erase(pos);
250
                if(options.fmt==Options::Bin) outputFileName+=".bin";
251
                else outputFileName+=".txt";
252
        }
253
 
254
        std::unique_ptr<OutputWriter> writer;
255
 
256
        switch(options.fmt) {
257
        case Options::Bin:
258
                writer=std::unique_ptr<OutputWriter>(new BinaryOutputWriter(outputFileName));
259
                break;
260
        case Options::Textio:
261
                writer=std::unique_ptr<OutputWriter>(new TextOutputWriter(outputFileName,TextOutputWriter::Bin));
262
                break;
263
        case Options::Dec:
264
                writer=std::unique_ptr<OutputWriter>(new TextOutputWriter(outputFileName,TextOutputWriter::Dec));
265
                break;
266
        case Options::Hex:
267
                writer=std::unique_ptr<OutputWriter>(new TextOutputWriter(outputFileName,TextOutputWriter::Hex));
268
                break;
269
        default:
270
                assert(false);
271
        }
272
 
273
        try {
274
                linker.link(*writer);
275
        }
276
        catch(std::exception &ex) {
277
                writer->abort();
278
                std::cerr<<"Linker error: "<<ex.what()<<std::endl;
279
                return EXIT_FAILURE;
280
        }
281
}
282
catch(std::exception &ex) {
283
        std::cerr<<"Error: "<<ex.what()<<std::endl;
284
        return EXIT_FAILURE;
285
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.