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

Subversion Repositories forwardcom

[/] [forwardcom/] [bintools/] [assem3.cpp] - Blame information for rev 101

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

Line No. Rev Author Line
1 43 Agner
/****************************    assem3.cpp    ********************************
2
* Author:        Agner Fog
3
* Date created:  2017-04-17
4
* Last modified: 2020-05-17
5
* Version:       1.10
6
* Project:       Binary tools for ForwardCom instruction set
7
* Module:        assem.cpp
8
* Description:
9
* Module for assembling ForwardCom .as files.
10
* This module contains:
11
* Assemble-time variable assignments and metaprogramming features,
12
* Copyright 2017-2020 GNU General Public License http://www.gnu.org/licenses
13
******************************************************************************/
14
#include "stdafx.h"
15
 
16
// Replace meta variables defined in previous '%' line
17
void CAssembler::replaceKnownNames() {
18
    // loop through tokens, replace known symbol names by reference to symbol records
19
    // and replace assemble-time variables by their current value
20
    uint32_t tok;                                // token index
21
    int32_t symi;                                // symbol index
22
    for (tok = tokenB; tok < tokenB + tokenN; tok++) {
23
        if (lineError) break;
24
        if (tokens[tok].type == TOK_NAM) {
25
            // name found. search for it in symbol table
26
            symi = findSymbol((char*)buf() + tokens[tok].pos, tokens[tok].stringLength);
27
            if (symi > 0) {  // symbol found. replace token by reference to symbol                
28
                tokens[tok].id = symbols[symi].st_name;  // use name offset as unique identifier because symbol index can change
29
                if (symbols[symi].st_type == STT_EXPRESSION) {
30
                    tokens[tok].type = TOK_XPR;
31
                    // save value of meta variable in token in case it changes later
32
                    tokens[tok].value.u = symbols[symi].st_value;
33
                }
34
                else if (symbols[symi].st_type == STT_TYPENAME) {    // symbol is an alias for a type name
35
                    if (tokens[tokenB].id != '%' || tok != tokenB + 1) { // replace it unless it comes immediately after %, which means it is redefined
36
                        tokens[tok].type = TOK_TYP;
37
                        tokens[tok].value.u = symbols[symi].st_value;
38
                        tokens[tok].id = (uint32_t)symbols[symi].st_value;
39
                    }
40
                }
41
                else {
42
                    tokens[tok].type = TOK_SYM;
43
                    if ((symbols[symi].st_type & ~1) == STT_CONSTANT) {
44
                        // save value of meta variable in token in case it changes later
45
                        tokens[tok].value.u = symbols[symi].st_value;
46
                        tokens[tok].vartype = 3;
47
                        if (symbols[symi].st_other & STV_FLOAT) {
48
                            tokens[tok].vartype = 5;
49
                        }
50
                    }
51
                }
52
            }
53
        } /*  not needed because meta code cannot have forward references, except in public directives which are handled elsewhere
54
        else if (tokens[tok].type == TOK_SYM) {
55
            symi = findSymbol(tokens[tok].value.w);
56
            if ((symbols[symi].st_type & ~1) == STT_CONSTANT) {
57
                // save value of meta variable in token in case it changes later
58
                tokens[tok].value.u = symbols[symi].st_value;
59
                tokens[tok].vartype = symbols[symi].st_reguse1;
60
            }
61
        } */
62
    }
63
}
64
 
65
 
66
// Interpret line beginning with '%' containing meta code
67
void CAssembler::interpretMetaDefinition() {
68
    uint32_t tok;                                // token index
69
    int32_t symi = 0;                            // symbol index
70
    ElfFWC_Sym2 sym;                             // symbol record
71
    zeroAllMembers(sym);                         // reset symbol
72
    //uint32_t tokmeta = 0;                        // token containing '%'
73
 
74
    // interpret line defining assemble-time variable
75
    uint32_t state = 0;   // state during definition of assemble-time variable:
76
                          // 1: after '%'
77
                          // 2: after type name
78
                          // 3: after variable name
79
                          // 4: after '=' or '+=', etc.
80
                          // 5: finished assignment
81
    uint32_t toktyp = 0;  // token containing type definition
82
    uint32_t tokop = 0;   // token containing ++ or -- operator
83
    uint32_t type = 3;    // default type is int64
84
    SExpression exps, expr;
85
    zeroAllMembers(expr);
86
 
87
    lineError = false;
88
    for (tok = tokenB; tok < tokenB + tokenN; tok++) {
89
        if (lineError)  break;
90
 
91
        if (state == 4) {
92
            // after assignment operator, expecting expression next
93
            expr = expression(tok, tokenB + tokenN - tok, 0);
94
            if (tok + expr.tokens < tokenB + tokenN) {
95
                errors.report(tokens[tok + expr.tokens]);  // extra tokens on line
96
            }
97
            exps = symbol2expression(symi); // make expression out of symbol
98
            if (lineError) break;
99
 
100
            // combine expressions
101
            switch (tokens[tok - 1].id) {
102
            case '=':  break;         // assign expr
103
            case '+' + EQ:            // +=
104
                expr = op2('+', exps, expr);  break;
105
            case '-' + EQ:            // -=
106
                expr = op2('-', exps, expr);  break;
107
            case '*' + EQ:            // *=
108
                expr = op2('*', exps, expr);  break;
109
            case '/' + EQ:            // /=
110
                expr = op2('/', exps, expr);  break;
111
            case '&' + EQ:            // &=
112
                expr = op2('&', exps, expr);  break;
113
            case '|' + EQ:            // |=
114
                expr = op2('|', exps, expr);  break;
115
            case '^' + EQ:            // ^=
116
                expr = op2('^', exps, expr);  break;
117
            case '<' + D2 + EQ:            // <<=
118
                expr = op2('<' + D2, exps, expr);  break;
119
            case '>' + D2 + EQ:            // >>=
120
                expr = op2('>' + D2, exps, expr);  break;
121
            case '>' + D3 + EQ:            // >>>=
122
                expr = op2('>' + D3, exps, expr);  break;
123
            default:
124
                errors.report(tokens[tok - 1].pos, tokens[tok - 1].stringLength, ERR_WRONG_TYPE);
125
            }
126
            if (expr.etype == uint32_t(XPR_ERROR)) {
127
                errors.report(tokens[tok - 1].pos, tokens[tok - 1].stringLength, expr.value.w);
128
            }
129
            else assignMetaVariable(symi, expr, toktyp);
130
            if (lineError) continue;
131
            state = 5;
132
            break;
133
        }
134
        if (state == 5) {
135
            errors.report(tokens[tok]);    // extra tokens on line
136
            return;
137
        }
138
        switch (tokens[tok].type) {
139
        case TOK_OPR:  // operator
140
            if (tokens[tok].id == '%' && state == 0) {
141
                state = 1;
142
            }
143
            else if (tokens[tok].priority == 15 && state == 3) state = 4; // assignment operator
144
            else if (tokens[tok].priority == 3) { // ++ or -- operator
145
                tokop = tok;
146
                if (state < 3) break;
147
                if (state == 3) {
148
                PLUSPLUSOPERATOR:
149
                    exps = symbol2expression(symi); // make expression out of symbol
150
                    expr.etype = XPR_INT;
151
                    expr.value.i = 1;
152
                    expr.tokens = 0;
153
                    switch (tokens[tokop].id) {
154
                    case '+' + D2:            // ++
155
                        expr = op2('+', exps, expr);  break;
156
                    case '-' + D2:            // --
157
                        expr = op2('-', exps, expr);  break;
158
                    default:
159
                        errors.report(tokens[tokop]);
160
                    }
161
                    if (expr.etype & XPR_ERROR) {
162
                        errors.report(tokens[tok - 1].pos, tokens[tok - 1].stringLength, expr.value.w);
163
                    }
164
                    else assignMetaVariable(symi, expr, toktyp);
165
                    lines[linei].type = LINE_METADEF;
166
                    state = 5;
167
                }
168
            }
169
            else tok = tokenB + tokenN;   // anything else. exit loop
170
            break;
171
        case TOK_TYP:  // type name
172
            toktyp = tok;  type = tokens[tok].vartype;
173
            if (state == 1) state = 2;
174
            break;
175
        case TOK_NAM:  // new name. define symbol
176
            if (state == 0) break;
177
            if (state >= 3) { errors.report(tokens[tok]);  break; }
178
            sym.st_name = symbolNameBuffer.putStringN((char*)buf() + tokens[tok].pos, tokens[tok].stringLength);
179
            symi = symbols.addUnique(sym);
180
            symbols[symi].st_type = 0;  // remember that symbol has no value yet
181
            symbols[symi].st_section = SECTION_LOCAL_VAR;  // remember symbol is not external. use arbitrary section
182
            symbols[symi].st_unitsize = 8;
183
            symbols[symi].st_unitnum = 1;
184
            tokens[tok].type = TOK_SYM;  // change token type
185
            tokens[tok].id = symbols[symi].st_name;
186
            tokens[tok].vartype = type;
187
            //if (state == 8) goto PLUSPLUSOPERATOR;
188
            state = 3;
189
            break;
190
        case TOK_SYM: case TOK_XPR: // existing symbol found
191
            if (state != 1 && state != 2) break;
192
            symi = findSymbol(tokens[tok].id);
193
            if (symi < 1) errors.report(tokens[tok]);    // unknown error
194
            if ((symbols[symi].st_type & ~1) == STT_CONSTANT) {
195
                symbols[symi].st_type = STT_VARIABLE;  // remember symbol has been modified
196
                if (tokop && tokop == tok - 1 && state < 3) goto PLUSPLUSOPERATOR;
197
            }
198
            state = 3;
199
            break;
200
        default:  // anything else. exit loop
201
            tok = tokenB + tokenN;
202
        }
203
    }
204
    // insert metaprogramming branches, loops and functions here??
205
}
206
 
207
 
208
// define or modify assemble-time constant or variable
209
void CAssembler::assignMetaVariable(uint32_t symi, SExpression & expr, uint32_t typetoken) {
210
    // get value and type from expression 
211
 
212
    symbols[symi].st_value = expr.value.u;
213
    uint32_t type = XPR_INT;
214
    // set variable type
215
    switch (expr.etype & 0xF) {
216
    case XPR_FLT:
217
        symbols[symi].st_other = STV_FLOAT;
218
        type = XPR_FLT;
219
        break;
220
    case XPR_STRING:
221
        symbols[symi].st_other = STV_STRING;
222
        symbols[symi].st_unitsize = 1;
223
        symbols[symi].st_unitnum = expr.sym2;    // string length
224
        type = XPR_STRING;
225
        break;
226
    default:
227
        symbols[symi].st_other = 0;
228
    }
229
    if (expr.etype & XPR_TYPENAME) symbols[symi].st_type = STT_TYPENAME;
230
    else if (symbols[symi].st_type == 0) symbols[symi].st_type = STT_CONSTANT;  // first time: make a constant
231
    else symbols[symi].st_type = STT_VARIABLE;                             // reassigned later: make a variable
232
    if (expr.etype & (XPR_REG | XPR_MEM)) {
233
        symbols[symi].st_type = STT_EXPRESSION;
234
        symbols[symi].st_value = expressions.push(expr);                         // save expression
235
    }
236
 
237
    // check expression type
238
    if (expr.etype & (XPR_OP | XPR_OPTION | XPR_SYMSCALE | XPR_MASK)) {
239
        errors.reportLine(ERR_WRONG_TYPE_VAR);
240
        return;
241
    }
242
    if ((expr.etype & (XPR_SYM1 | XPR_SYM2)) == XPR_SYM1 && !(expr.etype & XPR_MEM)) {
243
        // single symbol. must be constant or memory
244
        int32_t symi1 = findSymbol(expr.sym1);
245
        if (symi1 <= 0 || (!(symbols[symi1].st_type & STT_CONSTANT))) {
246
            errors.reportLine(ERR_WRONG_TYPE_VAR);
247
            return;
248
        }
249
    }
250
    // check if type matches
251
    if (typetoken == 0 || type == (tokens[typetoken].id & 0xF)) return;       // type matches
252
    if ((tokens[typetoken].id & 0xF) == XPR_FLT && type == XPR_INT) {
253
        // convert int to double
254
        expr.value.d = (double)expr.value.i;
255
        symbols[symi].st_value = expr.value.u;
256
        symbols[symi].st_other = STV_FLOAT;
257
        return;
258
    }
259
 
260
    errors.reportLine(ERR_WRONG_TYPE_VAR);
261
}

powered by: WebSVN 2.1.0

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