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

Subversion Repositories or1k

[/] [or1k/] [tags/] [stable_0_2_0_rc2/] [or1ksim/] [cpu/] [common/] [parse.c] - Blame information for rev 36

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

Line No. Rev Author Line
1 2 cvs
/* parce.c -- Architecture independent load and parsing of assembly
2
   Copyright (C) 1999 Damjan Lampret, lampret@opencores.org
3
 
4
This file is part of OpenRISC 1000 Architectural Simulator.
5
 
6
This program is free software; you can redistribute it and/or modify
7
it under the terms of the GNU General Public License as published by
8
the Free Software Foundation; either version 2 of the License, or
9
(at your option) any later version.
10
 
11
This program is distributed in the hope that it will be useful,
12
but WITHOUT ANY WARRANTY; without even the implied warranty of
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
GNU General Public License for more details.
15
 
16
You should have received a copy of the GNU General Public License
17
along with this program; if not, write to the Free Software
18
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
19
 
20
#include <stdio.h>
21
#include <ctype.h>
22
#include <string.h>
23
#include <stdlib.h>
24
 
25
#include "parse.h"
26
#include "abstract.h"
27 18 lampret
#include "arch.h"
28 28 lampret
#include "coff.h"
29 2 cvs
 
30
#define MAXLINE_LEN     18000
31
 
32 28 lampret
extern char *disassembled;
33
 
34 2 cvs
/* Unused mem memory marker. It is used when allocating program and data memory
35
   during parsing */
36
unsigned int freemem;
37
 
38
int nonempty(char *line)
39
{
40
        int i;
41
 
42
        for(i = 0; i < strlen(line); i++)
43
                if (!isspace(line[i]))
44
                        return(1);
45
        return(0);
46
}
47
 
48
int nondigit(char *line)
49
{
50
        int i;
51
 
52
        for(i = 0; i < strlen(line); i++)
53
                if (!isdigit(line[i]))
54
                        return(1);
55
        return(0);
56
}
57
 
58
char *strtoken(char *in, char *out, int which)
59
{
60
        char    *super;
61
        char    *sub;
62
        char    *newline;
63
 
64
        super = strdup(in);
65
        sub = strtok(super, " \t");
66
        while (sub && --which)
67
                sub = strtok(NULL, " \t");
68
        if (sub && !which) {
69
                if ((newline = strchr(sub, '\n')))
70
                        newline[0] = '\0';
71
                strcpy(out, sub);
72
        } else
73
                out[0] = '\0';
74
        free(super);
75
        if ((newline = strchr(out, '\r')))      /* get rid of CR */
76
                newline[0] = '\0';
77
        return(out);
78
}
79
 
80
void adddatastr(char *str)
81
{
82
        if (str)
83
                str++;
84
        else
85
                return;
86
 
87
        for(; *str && *str != '\"'; str++, freemem++)
88
                if (*str == '\\')
89
                        switch (*++str) {
90
                                case 'n': mem[freemem].data = '\n';
91
                                        break;
92
                                case 't': mem[freemem].data = '\t';
93
                                        break;
94
                                case 'r': mem[freemem].data = '\r';
95
                                        break;
96
                                case '0': mem[freemem].data = '\0';
97
                                        break;
98
                                default: break;
99
                        }
100
                else
101
                        mem[freemem].data = *str;
102
}
103
 
104 26 lampret
void adddataword(char *item)
105 2 cvs
{
106 26 lampret
        unsigned long num;
107 2 cvs
 
108 26 lampret
        if (isdigit(*item))
109 36 lampret
                num = strtoul(item, NULL, 0);
110 26 lampret
        else
111
                num = eval_label(item);
112
 
113
        debug("adddataword: [0x%x] <= %x\n", freemem, num);
114
        mem[freemem].data = (char) (num >> 24);
115
        mem[freemem + 1].data = (char) (num >> 16);
116
        mem[freemem + 2].data = (char) (num >> 8);
117
        mem[freemem + 3].data = (char) (num);
118
 
119 2 cvs
        freemem += 4;
120
}
121
 
122 26 lampret
void adddatahalf(char *item)
123 2 cvs
{
124 26 lampret
        unsigned long num;
125 2 cvs
 
126 26 lampret
        if (isdigit(*item))
127 36 lampret
                num = strtoul(item, NULL, 0);
128 26 lampret
        else
129
                num = eval_label(item);
130
 
131
        mem[freemem].data = (char) (num >> 8);
132
        mem[freemem + 1].data = (char) (num);
133
 
134 2 cvs
        freemem += 2;
135
}
136
 
137 26 lampret
void adddatabyte(char *item)
138 2 cvs
{
139 26 lampret
        unsigned long num;
140 2 cvs
 
141 26 lampret
        if (isdigit(*item))
142 36 lampret
                num = strtoul(item, NULL, 0);
143 26 lampret
        else
144
                num = eval_label(item);
145
 
146
        mem[freemem].data = (char) (num);
147
 
148 2 cvs
        freemem++;
149
}
150
 
151
void adddataspace(char *num)
152
{
153
        freemem += atol(num);
154
}
155
 
156 28 lampret
void addlabel(char *label, unsigned long freemem)
157 2 cvs
{
158 28 lampret
        struct label_entry **tmp;
159 2 cvs
 
160 30 lampret
        printf("adding label %s at 0x%x\n", label, freemem);
161 28 lampret
        tmp = &mem[freemem].label;
162
        for (; *tmp; tmp = &((*tmp)->next));
163
        *tmp = malloc(sizeof(**tmp));
164
        (*tmp)->name = malloc(strlen(label)+1);
165
        strcpy((*tmp)->name, label);
166
        (*tmp)->next = NULL;
167
 
168 2 cvs
        return;
169
}
170
 
171 28 lampret
char null_str[1] = "\0";
172
 
173 2 cvs
void addprogram(char *insn, char *operands)
174
{
175 18 lampret
        int h_insn_is_word_flag=0;
176
        char insn_first2_char[3];
177
 
178 28 lampret
        debug("addprogram 1\n");
179
        if (!mem[freemem].insn) {
180
                mem[freemem].insn = malloc(sizeof(*mem[freemem].insn));
181
                mem[freemem].insn->insn = null_str;
182
                mem[freemem].insn->op1 = null_str;
183
                mem[freemem].insn->op2 = null_str;
184
                mem[freemem].insn->op3 = null_str;
185
                mem[freemem].insn->op4 = null_str;
186
        } else {
187
                printf("internal error: reloading the same location\n");
188
                exit(1);
189
        }
190
        debug("addprogram 2\n");
191
 
192
        mem[freemem].insn->insn = malloc(strlen(insn)+1);
193
 
194
#ifdef  OR16
195
 
196
        strcpy(mem[freemem].insn->insn, insn);
197
        printf("half:%s:\n", insn);
198 18 lampret
        insn_first2_char[0]=insn[0];
199
        insn_first2_char[1]=insn[1];
200
        insn_first2_char[2]='\0';
201 28 lampret
        debug("addprogram 3\n");
202 2 cvs
 
203 18 lampret
        if(strcmp("h.", insn_first2_char) == 0) {
204
                if(strcmp("h.load32u", insn) == 0 ||
205
                   strcmp("h.load16u", insn) == 0 ||
206
                   strcmp("h.load8u", insn) == 0 ||
207
                   strcmp("h.stor32", insn) == 0 ||
208
                   strcmp("h.stor16", insn) == 0 ||
209
                   strcmp("h.stor8", insn) == 0 ||
210
                   strcmp("h.jal", insn) == 0 ||
211 22 lampret
                   /* strcmp("h.mtsr", insn) == 0 ||
212
                   strcmp("h.mfsr", insn) == 0 || */
213 18 lampret
                   strcmp("h.movi16ze", insn) == 0 ||
214
                   strcmp("h.immhi16u", insn) == 0 ||
215
                   strcmp("h.addi16s", insn) == 0 ||
216
                   strcmp("h.subi16s", insn) == 0 ||
217
                   strcmp("h.xori16", insn) == 0 ||
218
                   strcmp("h.ori16", insn) == 0 ||
219
                   strcmp("h.andi16", insn) == 0
220
                  )
221
                        h_insn_is_word_flag = 2; /* h.xxx insn AND occupy 4 bytes */
222
                else
223
                        h_insn_is_word_flag = 1; /* h.xxx insn AND occupy 2 bytes */
224
        }
225
        else {
226
                        h_insn_is_word_flag = 0; /* not h.xxx insn */
227
        }
228
#else
229 28 lampret
        debug("addprogram 4\n");
230
        strcpy(mem[freemem].insn->insn, insn);
231
        debug("addprogram 5\n");
232 18 lampret
#endif
233
 
234 2 cvs
        /* op1 */
235 28 lampret
        if (*operands) {
236
                mem[freemem].insn->op1 = malloc(strlen(operands)+1);
237
                strcpy(mem[freemem].insn->op1, operands);
238
        }
239
 
240
        debug("addprogram 6\n");
241
        debug("operands:%s\n", operands);
242
        if (strstr(operands, OPERAND_DELIM)) {
243
                debug("addprogram 6a\n");
244
                operands = strstr(mem[freemem].insn->op1, OPERAND_DELIM);
245 2 cvs
                *operands = '\0';
246
                operands++;
247
        } else {
248 28 lampret
                debug("addprogram 6b\n");
249
#ifdef OR16
250 18 lampret
                freemem += (h_insn_is_word_flag == 1) ? 2 : 4;
251
#else
252 2 cvs
                freemem += 4;
253 18 lampret
#endif
254 2 cvs
                return;
255
        }
256
 
257 28 lampret
        debug("addprogram 7\n");
258 2 cvs
        /* op2 */
259 28 lampret
        if (*operands) {
260
                mem[freemem].insn->op2 = malloc(strlen(operands)+1);
261
                strcpy(mem[freemem].insn->op2, operands);
262
        }
263
        if (strstr(operands, OPERAND_DELIM)) {
264
                operands = strstr(mem[freemem].insn->op2, OPERAND_DELIM);
265 2 cvs
                *operands = '\0';
266
                operands++;
267
        } else {
268 28 lampret
#ifdef OR16
269 18 lampret
                freemem += (h_insn_is_word_flag == 1) ? 2 : 4;
270
#else
271 2 cvs
                freemem += 4;
272 18 lampret
#endif
273 2 cvs
                return;
274
        }
275
 
276 28 lampret
        debug("addprogram 8\n");
277 2 cvs
        /* op3 */
278 28 lampret
        if (*operands) {
279
                mem[freemem].insn->op3 = malloc(strlen(operands)+1);
280
                strcpy(mem[freemem].insn->op3, operands);
281
        }
282
        if (strstr(operands, OPERAND_DELIM)) {
283
                operands = strstr(mem[freemem].insn->op3, OPERAND_DELIM);
284 2 cvs
                *operands = '\0';
285
                operands++;
286
        } else {
287 28 lampret
#ifdef OR16
288 18 lampret
                freemem += (h_insn_is_word_flag == 1) ? 2 : 4;
289
#else
290 2 cvs
                freemem += 4;
291 18 lampret
#endif
292 2 cvs
                return;
293
        }
294
 
295
        /* op4 */
296 28 lampret
        if (*operands) {
297
                mem[freemem].insn->op4 = malloc(strlen(operands)+1);
298
                strcpy(mem[freemem].insn->op4, operands);
299
        }
300
        if (strstr(operands, OPERAND_DELIM)) {
301
                operands = strstr(mem[freemem].insn->op4, OPERAND_DELIM);
302 2 cvs
                *operands = '\0';
303
                operands++;
304
        }
305
 
306 28 lampret
#ifdef OR16
307 18 lampret
                freemem += (h_insn_is_word_flag == 1) ? 2 : 4;
308
#else
309
                freemem += 4;
310
#endif
311 2 cvs
        return;
312
}
313
 
314
/* Non-architecture dependent parsing: stripping comments, filling
315
   abstract memory */
316
 
317
void parseline(char *inputline)
318
{
319
        char item[MAXLINE_LEN];
320
        char item2[MAXLINE_LEN];
321
        int  i = 0;
322
 
323
        /* Strip comments: simply terminate line where
324
           the first comment character appears. */
325
 
326
        debug("PARSING: %s", inputline);
327
        while (inputline[i] != '\0')
328
                if (inputline[i] == COMMENT_CHAR) {
329
                        inputline[i] = '\0';
330
                        break;
331
                } else
332
                        i++;
333
 
334
        /* Get the first item from this line */
335 18 lampret
        strtoken(inputline, item, 1);   /* opcode */
336
        strtoken(inputline, item2, 2);  /* all the remaining one/two/three operands */
337 2 cvs
 
338
        /* Is this item empty? Nothing to process, so return. */
339
        if (strlen(item) == 0)
340
                return;
341
 
342 18 lampret
        /* Is this item a label? If yes, add it to the label table and return immediately. */
343 2 cvs
        if (strstr(item, LABELEND_CHAR)) {
344 28 lampret
                *strstr(item, LABELEND_CHAR) = '\0';
345
                addlabel(item, freemem);
346 2 cvs
                return;
347
        }
348
 
349
        /* Is this item a .directive? If yes, check for some supported
350
           and then return (even if unsupported found). */
351
        if (item[0] == DIRECTIVE_CHAR) {
352 28 lampret
                if (strcmp(item, ".align") == 0) {
353 30 lampret
                        int align = strtoul(item2, NULL, 0);
354 28 lampret
                        if (!(freemem % align))
355
                                return;
356
                        freemem &= -align;
357
                        freemem += align;
358 2 cvs
                        return;
359
                } else
360 30 lampret
                if (strcmp(item, ".org") == 0) {
361
                        int addr = strtoul(item2, NULL, 0);
362
                        freemem = addr;
363
                        return;
364
                } else
365 2 cvs
                if (strcmp(item, ".ascii") == 0) {
366
                        adddatastr(strstr(inputline, "\""));
367
                        return;
368
                } else
369
                if (strcmp(item, ".word") == 0) {
370
                        adddataword(item2);
371
                        return;
372
                } else
373
                if (strcmp(item, ".half") == 0) {
374
                        adddatahalf(item2);
375
                        return;
376
                } else
377
                if (strcmp(item, ".byte") == 0) {
378
                        adddatabyte(item2);
379
                        return;
380
                } else
381
                if (strcmp(item, ".space") == 0) {
382
                        adddataspace(item2);
383
                        return;
384
                } else  /* .directive but not one of the supported */
385
                        return;
386
        }
387
 
388
        /* This item can only be an instruction. Get all operands
389
           and add everything to mem array but as a program. */
390 28 lampret
        debug("%x: ", freemem);
391 2 cvs
        addprogram(item, item2);
392
 
393
        /* Also do static, single stats. */
394
        addsstats(item, 0, 1);
395
 
396
        return;
397
 
398
}
399
 
400 28 lampret
/* Load big-endian COFF file. At the moment it doesn't load symbols yet. */
401
 
402
void readfile_coff(char *filename, short sections)
403
{
404
        FILE *inputfs;
405
        char inputbuf[4];
406
        unsigned long insn;
407
        signed long tstart, tsize, dstart, dsize;
408
        COFF_AOUTHDR coffaouthdr;
409
        struct COFF_scnhdr coffscnhdr;
410
        int  len;
411
        char item[MAXLINE_LEN];
412
        char item2[MAXLINE_LEN];
413
 
414
 
415
        if (!(inputfs = fopen(filename, "r"))) {
416
                perror("readfile_coff");
417
                exit(1);
418
        }
419
 
420
        if (fseek(inputfs, sizeof(struct COFF_filehdr), SEEK_SET) == -1) {
421
                fclose(inputfs);
422
                perror("readfile_coff");
423
                exit(1);
424
        }
425
 
426
        if (fread(&coffaouthdr, sizeof(coffaouthdr), 1, inputfs) != 1) {
427
                fclose(inputfs);
428
                perror("readfile_coff");
429
                exit(1);
430
        }
431
 
432
        tstart = COFF_LONG_H(coffaouthdr.text_start);
433
        dstart = COFF_LONG_H(coffaouthdr.data_start);
434
        tsize = COFF_LONG_H(coffaouthdr.tsize);
435
        dsize = COFF_LONG_H(coffaouthdr.dsize);
436
        printf("text_start: %x, ", tstart);
437
        printf("tsize: %x, ", tsize);
438
        printf("data_start: %x, ", dstart);
439
        printf("dsize: %x\n", dsize);
440
 
441
        while(sections--) {
442
                if (fread(&coffscnhdr, sizeof(struct COFF_scnhdr), 1, inputfs) != 1) {
443
                        fclose(inputfs);
444
                        perror("readfile_coff");
445
                        exit(1);
446
                }
447
                printf("Section: %s,", coffscnhdr.s_name);
448
                printf(" size: 0x%.4x,", COFF_LONG_H(coffscnhdr.s_size));
449
                printf(" scnptr: 0x%.4x\n", COFF_LONG_H(coffscnhdr.s_scnptr));
450
        }
451
 
452
        /* loading .text section */
453
        while ((len = fread(&inputbuf, sizeof(inputbuf), 1, inputfs))) {
454
                insn = COFF_LONG_H(inputbuf);
455
                len = disassemble_insn(insn);
456 36 lampret
                sprintf(item, "%u", insn);
457
                adddataword(item);
458
                freemem -= len;
459 28 lampret
                if (len == 2) {
460
                        fseek(inputfs, -2, SEEK_CUR);
461
                        printf("readfile_coff: %x 0x%x   ", tsize, insn >> 16);
462
                }
463
                else
464
                        printf("readfile_coff: %x 0x%x   ", tsize, insn);
465
                printf("%s\n", disassembled);
466
                strtoken(disassembled, item, 1); /* opcode */
467
                strtoken(disassembled, item2, 2); /* all the remaining one/two/three operands */
468
                addprogram(item, item2);
469
                tsize -= len;
470
                if (tsize <= 0)
471
                        break;
472
        }
473
        fclose(inputfs);
474
        printf("Finished loading COFF.\n");
475
        return;
476
}
477
 
478
/* Load symbols from big-endian COFF file. */
479
 
480
void readsyms_coff(char *filename, unsigned long symptr, long syms)
481
{
482
        FILE *inputfs;
483
        struct COFF_syment coffsymhdr;
484
 
485
 
486
        if (!(inputfs = fopen(filename, "r"))) {
487
                perror("readsyms_coff");
488
                exit(1);
489
        }
490
 
491
        if (fseek(inputfs, symptr, SEEK_SET) == -1) {
492
                fclose(inputfs);
493
                perror("readsyms_coff");
494
                exit(1);
495
        }
496
 
497
        while(syms--) {
498
                if (fread(&coffsymhdr, COFF_SYMESZ, 1, inputfs) != 1) {
499
                        fclose(inputfs);
500
                        perror("readsyms_coff");
501
                        exit(1);
502
                }
503
                printf("Symbol: %s,", coffsymhdr.e.e_name);
504
                printf(" val: 0x%.8x,", COFF_LONG_H(coffsymhdr.e_value));
505
                printf(" auxs: %c\n", coffsymhdr.e_numaux);
506
                if (strlen(coffsymhdr.e.e_name))
507
                        addlabel(coffsymhdr.e.e_name, COFF_LONG_H(coffsymhdr.e_value));
508
        }
509
 
510
        fclose(inputfs);
511
        printf("Finished loading symbols.\n");
512
        return;
513
}
514
 
515 2 cvs
/* Load file and hand over every line to parse routine. */
516
 
517 28 lampret
void readfile_assembly(char *filename)
518 2 cvs
{
519
        FILE *inputfs;
520
        char  inputbuf[MAXLINE_LEN];
521
        char  *status;
522
 
523 28 lampret
        if (!(inputfs = fopen(filename, "r"))) {
524
                perror("readfile_assembly");
525
                exit(1);
526
        }
527
 
528
        while ((status = fgets(inputbuf, sizeof(inputbuf), inputfs))) {
529
                if (nonempty(inputbuf))
530
                        parseline(inputbuf);
531
        }
532
        fclose(inputfs);
533
 
534
        return;
535
}
536
 
537
/* Identify file type and call appropriate readfile_X routine. It only
538
handles orX-coff-big executables at the moment. */
539
 
540
void identifyfile(char *filename)
541
{
542
        FILE *inputfs;
543
        struct COFF_filehdr coffhdr;
544
        size_t len;
545
 
546
        if (!(inputfs = fopen(filename, "r"))) {
547
                perror("identifyfile");
548
                exit(1);
549
        }
550
 
551
        if (fread(&coffhdr, sizeof(coffhdr), 1, inputfs) == 1) {
552
                if (COFF_SHORT_H(coffhdr.f_magic) == 0x17a) {
553
                        unsigned long opthdr_size;
554
                        printf("COFF magic: 0x%.4x\n", COFF_SHORT_H(coffhdr.f_magic));
555
                        printf("COFF flags: 0x%.4x\n", COFF_SHORT_H(coffhdr.f_flags));
556
                        printf("COFF symptr: 0x%.8x\n", COFF_LONG_H(coffhdr.f_symptr));
557
                        if ((COFF_SHORT_H(coffhdr.f_flags) & COFF_F_EXEC) != COFF_F_EXEC) {
558
                                printf("This COFF is not an executable.\n");
559
                                exit(1);
560
                        }
561
                        opthdr_size = COFF_SHORT_H(coffhdr.f_opthdr);
562
                        if (opthdr_size != sizeof(COFF_AOUTHDR)) {
563
                                printf("COFF optional header is missing or not recognized.\n");
564
                                printf("COFF f_opthdr: 0x%.2x\n", opthdr_size);
565
                                exit(1);
566
                        }
567
                        fclose(inputfs);
568
                        readfile_coff(filename, COFF_SHORT_H(coffhdr.f_nscns));
569
                        readsyms_coff(filename, COFF_LONG_H(coffhdr.f_symptr), COFF_LONG_H(coffhdr.f_nsyms));
570
                        return;
571 2 cvs
                }
572 28 lampret
                else {
573
                        printf("Not COFF, trying to load as assembly.\n");
574
                        fclose(inputfs);
575
                        readfile_assembly(filename);
576
                        return;
577
                }
578 2 cvs
        }
579
        else
580 28 lampret
                perror("identifyfile");
581 2 cvs
 
582 28 lampret
        fclose(inputfs);
583
 
584 2 cvs
        return;
585
}
586
 
587
void loadcode(char *filename)
588
{
589 30 lampret
        freemem = MEMORY_START;
590 2 cvs
        memset(mem, 0, sizeof(mem));
591 28 lampret
        identifyfile(filename);
592 2 cvs
        return;
593
}

powered by: WebSVN 2.1.0

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