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

Subversion Repositories forwardcom

[/] [forwardcom/] [bintools/] [assem.h] - Blame information for rev 65

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 65 Agner
/****************************    assem.h    ***********************************
2
* Author:        Agner Fog
3
* Date created:  2017-04-17
4
* Last modified: 2021-05-26
5
* Version:       1.11
6
* Project:       Binary tools for ForwardCom instruction set
7
* Module:        assem.h
8
* Description:
9
* Header file for assembler
10
*
11
* Copyright 2017-2021 GNU General Public License http://www.gnu.org/licenses
12
*****************************************************************************/
13
#pragma once
14
 
15
// Define token types:
16
const int  TOK_EOF = 1;                // end of file
17
const int  TOK_NAM = 2;                // unidentified name
18
const int  TOK_LAB = 3;                // code label or function name
19
const int  TOK_VAR = 4;                // data label
20
const int  TOK_SEC = 5;                // section name
21
const int  TOK_INS = 6;                // instruction name
22
const int  TOK_OPR = 7;                // operator
23
const int  TOK_NUM = 8;                // integer number
24
const int  TOK_FLT = (TOK_NUM + 1);    // floating point number
25
const int  TOK_CHA = 0x0A;             // character or string in single quotes ' '
26
const int  TOK_STR = 0x0B;             // string in double quotes " "
27
const int  TOK_DIR = 0x11;             // section or function directive
28
const int  TOK_ATT = 0x12;             // attribute of sections, functions, or symbols. also some keywords
29
const int  TOK_TYP = 0x14;             // type identifier
30
const int  TOK_OPT = 0x15;             // options of instructions and operands
31
const int  TOK_REG = 0x16;             // register name
32
const int  TOK_SYM = 0x1A;             // symbol, constant, variable, function. id = symbol index
33
const int  TOK_XPR = 0x1B;             // expression. id = expression index
34
const int  TOK_HLL = 0x20;             // high level language block (if, for, etc.)
35
const int  TOK_ERR = 0x80;             // error. illegal character or unmatched quote
36
 
37
// Define keyword id's:
38
 
39
// Directives
40
const int DIR_SECTION  = ((TOK_DIR << 24) + 1);
41
const int DIR_FUNCTION = ((TOK_DIR << 24) + 2);
42
const int DIR_END      = ((TOK_DIR << 24) + 4);
43
const int DIR_PUBLIC   = ((TOK_DIR << 24) + 8);
44
const int DIR_EXTERN   = ((TOK_DIR << 24) + 0x10);
45
 
46
// Attributes of sections
47
const int ATT_READ     = ((TOK_ATT << 24) + SHF_READ);
48
const int ATT_WRITE    = ((TOK_ATT << 24) + SHF_WRITE);
49
const int ATT_EXEC     = ((TOK_ATT << 24) + SHF_EXEC);
50
const int ATT_ALIGN    = ((TOK_ATT << 24) + 0x10);
51
const int SECTION_LOCAL_VAR = 0xFFFFFFFF;                       // local constant with no section
52
 
53
// Attributes of variables, constants and functions
54
const int ATT_WEAK     = ((TOK_ATT << 24) + 0x20);              // weak public or weak external symbol
55
const int ATT_REGUSE   = ((TOK_ATT << 24) + 0x21);              // register use of function
56
const int ATT_CONSTANT = ((TOK_ATT << 24) + 0x10000);           // used for external constants
57
const int ATT_UNINIT   = ((TOK_ATT << 24) + 0x20000);           // uninitialized section (BSS)
58
const int ATT_COMDAT   = ((TOK_ATT << 24) + 0x40000);           // communal section. duplicates and unreferenced sections are removed
59
const int ATT_EXCEPTION= ((TOK_ATT << 24) + SHF_EXCEPTION_HND); // exception handler info
60
const int ATT_EVENT    = ((TOK_ATT << 24) + SHF_EVENT_HND);     // event handler info
61
const int ATT_DEBUG    = ((TOK_ATT << 24) + SHF_DEBUG_INFO);    // debug info
62
const int ATT_COMMENT  = ((TOK_ATT << 24) + SHF_COMMENT);       // comments
63
 
64
// Type definitions
65
const int TYP_INT8     = ((TOK_TYP << 24) + 0x10);
66
const int TYP_INT16    = ((TOK_TYP << 24) + 0x11);
67
const int TYP_INT32    = ((TOK_TYP << 24) + 0x12);
68
const int TYP_INT64    = ((TOK_TYP << 24) + 0x13);
69
const int TYP_INT128   = ((TOK_TYP << 24) + 0x14);
70
const int TYP_UNS                         = 0x20;   // add this for unsigned integer types
71
const int TYP_PLUS                       = 0x100;   // add this larger type allowed
72
const int TYP_FLOAT16  = ((TOK_TYP << 24) + 0x44);
73
const int TYP_FLOAT32  = ((TOK_TYP << 24) + 0x45);
74
const int TYP_FLOAT64  = ((TOK_TYP << 24) + 0x46);
75
const int TYP_FLOAT128 = ((TOK_TYP << 24) + 0x47);
76
const int TYP_INT      =                    0x10;    // generic test for int types
77
const int TYP_FLOAT    =                    0x40;    // generic test for float types
78
const int TYP_STRING   = ((TOK_TYP << 24) + 0x18);
79
 
80
// Options and attributes of instructions
81
const int OPT_MASK     = ((TOK_OPT << 24) + 1);
82
const int OPT_FALLBACK = ((TOK_OPT << 24) + 2);
83
const int OPT_LENGTH   = ((TOK_OPT << 24) + 3);
84
const int OPT_BROADCAST= ((TOK_OPT << 24) + 4);
85
const int OPT_LIMIT    = ((TOK_OPT << 24) + 5);
86
const int OPT_SCALAR   = ((TOK_OPT << 24) + 6);
87
const int OPT_OPTIONS  = ((TOK_OPT << 24) + 7);
88
 
89
// Register types
90
const int REG_R        =  0x20;        // general purpose register
91
const int REG_V        =  0x40;        // vector register
92
const int REG_SPEC     =  0x60;        // special register, accessed with read_spec and write_spec instructions
93
const int REG_CAPAB    =  0x80;        // capabilities register, accessed with read_capabilities
94
const int REG_PERF     =  0xA0;        // performance counter, accessed with read_perf
95
const int REG_SYS      =  0xC0;        // system register, accessed with read_sys and write_sys
96
const int REG_OTHER    = 0x100;        // other register, unclassified
97
 
98
// ID for special registers:
99
// bit 0-4   is the id used when reading or writing the register
100
// bit 5-7   indicate the type of register
101
// bit 16-20 is the id when the register is used as base pointer
102
// bit 24-31 is token type
103
const int REG_NUMCONTR = ((TOK_REG << 24) +                REG_SPEC + 0);    // numeric control register, default flag
104
const int REG_THREADP  = ((TOK_REG << 24) + (0x1C << 16) + REG_SPEC + 1);    // thread data pointer
105
const int REG_DATAP    = ((TOK_REG << 24) + (0x1D << 16) + REG_SPEC + 2);    // data section pointer
106
const int REG_IP       = ((TOK_REG << 24) + (0x1E << 16) + REG_OTHER   );    // instruction pointer, changed by jump instructions
107
const int REG_SP       = ((TOK_REG << 24) + (0x1F << 16) + REG_R + 0x1F);    // stack pointer
108
 
109
// high level language directives
110
const int HLL_IF       = ((TOK_HLL << 24) + 1);
111
const int HLL_ELSE     = ((TOK_HLL << 24) + 2);
112
const int HLL_SWITCH   = ((TOK_HLL << 24) + 3);
113
const int HLL_CASE     = ((TOK_HLL << 24) + 4);
114
const int HLL_FOR      = ((TOK_HLL << 24) + 5);
115
const int HLL_IN       = ((TOK_HLL << 24) + 6);
116
const int HLL_NOCHECK  = ((TOK_HLL << 24) + 7);
117
const int HLL_WHILE    = ((TOK_HLL << 24) + 8);
118
const int HLL_DO       = ((TOK_HLL << 24) + 9);
119
const int HLL_BREAK    = ((TOK_HLL << 24) + 10);
120
const int HLL_CONTINUE = ((TOK_HLL << 24) + 11);
121
 
122
const int HLL_FALSE    = ((TOK_HLL << 24) + 20);
123
const int HLL_TRUE     = ((TOK_HLL << 24) + 21);
124
 
125
// push and pop may be replaced by macros later:
126
const int HLL_PUSH     = ((TOK_HLL << 24) + 12);
127
const int HLL_POP      = ((TOK_HLL << 24) + 13);
128
 
129
// line types
130
const int LINE_DATADEF =    1;                   // data definition
131
const int LINE_CODEDEF =    2;                   // code instruction
132
const int LINE_PUBLICDEF =  3;                   // public symbol definition
133
const int LINE_METADEF =    4;                   // assemble-time definitions and metaprogramming
134
const int LINE_OPTIONS =    5;                   // option setting
135
const int LINE_FUNCTION= 0x11;                   // function definition
136
const int LINE_SECTION = 0x12;                   // section definition
137
const int LINE_ENDDIR  = 0x10;                   // function or section end
138
const int LINE_ERROR   = 0xFF;                   // error detected in this line
139
 
140
// Operator id's are equal to the ASCII code with these additions:
141
const int EQ = 0x100;                  // operator followed by equal sign, e.g. +=
142
const int D2 = 0x200;                  // operator repeated, e.g. <<
143
const int D3 = 0x400;                  // operator triple, e.g. >>>
144
const int OP_UNS = 0x1000;             // unsigned operation
145
 
146
// SExpression types in .etype
147
const int XPR_INT           = 0x01;    // contains integer value
148
const int XPR_INT2          = 0x02;    // contains a second integer constant in the upper half of value
149
const int XPR_FLT           = 0x04;    // contains floating point value
150
const int XPR_IMMEDIATE     = 0x07;    // contains immediate constant
151
const int XPR_STRING        = 0x08;    // contains string (u = string buffer entry, sym2 = length)
152
const int XPR_REG           = 0x10;    // contains register operand
153
const int XPR_OP            = 0x20;    // contains instruction or operator
154
const int XPR_OPTION        = 0x80;    // contains option keyword for memory operand
155
const int XPR_MEM          = 0x100;    // contains memory operand, or part of it
156
const int XPR_SYM1         = 0x200;    // contains symbol address
157
const int XPR_SYM2         = 0x400;    // contains reference symbol address
158
const int XPR_SYMSCALE     = 0x800;    // contains scale factor on (sym1-sym2)
159
const int XPR_REG1        = 0x1000;    // contains first register operand
160
const int XPR_REG2        = 0x2000;    // contains second register operand
161
const int XPR_REG3        = 0x4000;    // contains third register operand in value.u
162
const int XPR_BASE        = 0x8000;    // contains base register
163
const int XPR_INDEX      = 0x10000;    // contains index register and scale factor
164
const int XPR_OFFSET     = 0x20000;    // contains memory address offset
165
const int XPR_LIMIT      = 0x40000;    // contains limit for index
166
const int XPR_SCALAR     = 0x80000;    // contains scalar memory operand without broadcast
167
const int XPR_LENGTH    = 0x100000;    // contains vector length register
168
const int XPR_BROADC    = 0x200000;    // contains vector broadcast length register
169
const int XPR_MASK      = 0x400000;    // contains mask register
170
const int XPR_FALLBACK  = 0x800000;    // contains fallback register
171
const int XPR_OPTIONS  = 0x1000000;    // contains options or signbits in IM3
172
const int XPR_JUMPOS   = 0x2000000;    // contains self-relative jump offset
173
const int XPR_TYPENAME =0x10000000;    // contains type name in value
174
const int XPR_UNRESOLV =0x40000000;    // contains unresolved name or value
175
const int XPR_ERROR    =0x80000000;    // an error occurred during the generation
176
 
177
// Instruction id's
178
const uint32_t II_NOP            =  0x30000;
179
const uint32_t II_STORE          =        1;
180
const uint32_t II_MOVE           =        2;
181
const uint32_t II_COMPARE        =        7;
182
const uint32_t II_ADD            =        8;
183
const uint32_t II_SUB            =        9;
184
const uint32_t II_SUB_REV        =       10;
185
const uint32_t II_MUL            =       11;
186
const uint32_t II_MUL_HI         =       12;
187
const uint32_t II_MUL_EX         =  0x1201A;
188
const uint32_t II_DIV            =       14;
189
const uint32_t II_DIV_U          =       15; // all unsigned variants must be signed variant | 1
190
const uint32_t II_DIV_REV        =       16;
191
const uint32_t II_DIV_EX         =  0x12018;
192
const uint32_t II_REM            =       18;
193
const uint32_t II_REM_U          =       19;
194
const uint32_t II_MIN            =       20;
195
const uint32_t II_MIN_U          =       21;
196
const uint32_t II_MAX            =       22;
197
const uint32_t II_MAX_U          =       23;
198
const uint32_t II_AND            =       26;
199
const uint32_t II_OR             =       27;
200
const uint32_t II_XOR            =       28;
201
const uint32_t II_SHIFT_LEFT     =       32;
202
const uint32_t II_MUL_2POW       =       32;
203
const uint32_t II_ROTATE         =       33;
204
const uint32_t II_SHIFT_RIGHT_S  =       34;
205
const uint32_t II_SHIFT_RIGHT_U  =       35;  // must be = II_SHIFT_RIGHT_S | 1
206
const uint32_t II_CLEAR_BIT      =       36;
207
const uint32_t II_SET_BIT        =       37;
208
const uint32_t II_TOGGLE_BIT     =       38;
209
const uint32_t II_TEST_BIT       =       39;
210
const uint32_t II_TEST_BITS_AND  =       40;
211
const uint32_t II_TEST_BITS_OR   =       41;
212
const uint32_t II_MUL_ADD        =       49;
213
const uint32_t II_MUL_ADD2       =       50;
214
const uint32_t II_ADD_ADD        =       51;
215
const uint32_t II_SELECT_BITS    =       52;
216
const uint32_t II_FUNNEL_SHIFT   =       53;
217
const uint32_t II_SHIFT_U_ADD    =   0x0101;
218
//const uint32_t II_MOVE_U         =   0x11001;
219
const uint32_t II_ADD_H          =  0x50008;  // float16
220
const uint32_t II_SUB_H          =  0x50009;  // float16
221
const uint32_t II_MUL_H          =  0x5000B;  // float16
222
const uint32_t II_DIV_H          =  0x50010;  // float16
223
const uint32_t II_MUL_ADD_H      =  0x50031;  // float16
224
const uint32_t II_PUSH           =  0x18038;
225
const uint32_t II_POP            =  0x18039;
226
const uint32_t II_REPLACE        =  0xA0001;
227
const uint32_t II_REPLACE_EVEN   =  0x26004;
228
const uint32_t II_REPLACE_ODD    =  0x26005;
229
const uint32_t II_ADDRESS        =  0x29020;
230
 
231
// constants for jump and branch instrucions. May be combined with II_ADD, II_SUB, II_COMPARE, etc. 
232
const uint32_t II_INCREMENT      =   0x0051;  // increment. combine with II_JUMP_POSITIVE
233
const uint32_t II_SUB_MAXLEN     =   0x0052;  // subtract max vector length. combine with II_JUMP_POSITIVE
234
const uint32_t II_FP_CATEGORY    =   0x0054;  // fp_category. combine with II_JUMP_TRUE
235
 
236
const uint32_t II_JUMP           = 0x101000;  // jump codes may be combined with II_ADD etc.
237
const uint32_t II_JUMP_ZERO      = 0x101200;  // xor with 0x100 for opposite condition
238
const uint32_t II_JUMP_NOTZERO   = 0x101300;  // not zero or not equal
239
const uint32_t II_JUMP_NEGATIVE  = 0x101400;  // negative or signed below
240
const uint32_t II_JUMP_POSITIVE  = 0x101600;  // positive or signed above
241
const uint32_t II_JUMP_OVERFLOW  = 0x101800;  // signed overflow
242
const uint32_t II_JUMP_CARRY     = 0x102000;  // carry, borrow, unsigned below, abs below. Reverse condition if 'sub n' replaced by 'add (-n)'
243
const uint32_t II_JUMP_UBELOW    = 0x102000;  // carry, borrow, unsigned below, abs below. Reverse condition if 'sub n' replaced by 'add (-n)'
244
const uint32_t II_JUMP_UABOVE    = 0x102200;  // unsigned above, abs above
245
const uint32_t II_JUMP_TRUE      = 0x102400;  // bit test etc. true
246
const uint32_t II_JUMP_FALSE     = 0x102500;  // bit test etc. false
247
const uint32_t II_JUMP_INVERT    =   0x0100;  // flip this bit to invert condition
248
const uint32_t II_JUMP_UNORDERED =   0x8000;  // flip this bit to jump if unordered
249
const uint32_t II_JUMP_INSTR     = 0x100000;  // bit to identify direct jump and call instructions
250
const uint32_t II_INCREMENT_COMPARE_JBELOW = 48; // opj for increment_compare_jump_below
251
const uint32_t II_CALL           = 0x111000;  // direct call
252
 
253
const uint32_t II_ALIGN        = 0x10000000;  // align directive
254
const uint32_t II_OPTIONS      = 0x20000000;  // options directive
255
 
256
const int MAX_ALIGN              =     4096;  // maximum allowed alignment  (note: if changed, change also in error.cpp at ERR_ALIGNMENT)
257
 
258
// Bit values generated by fitConstant() and stored in SCode::fitNumX
259
// Indicates how many bits are needed to contain address offset or immediate constant of an instruction
260
const int IFIT_I8        =     0x10;  // fits into signed 8-bit integer
261
const int IFIT_J8        =     0x20;  // (-x) fits into signed 8-bit integer
262
const int IFIT_U8        =     0x40;  // x fits into unsigned 8-bit integer
263
const int IFIT_I8SHIFT   =     0x80;  // fits into signed 8-bit integer with left shift
264
const int IFIT_I16       =    0x100;  // fits into signed 16-bit integer
265
const int IFIT_J16       =    0x200;  // (-x) fits into signed 16-bit integer
266
const int IFIT_U16       =    0x400;  // fits into unsigned 16-bit integer
267
const int IFIT_I16SHIFT  =    0x800;  // fits into signed 16-bit integer with left shift
268
const int IFIT_I16SH16   =   0x1000;  // fits into signed 16-bit integer shifted left by 16
269
const int IFIT_I24       =   0x4000;  // fits into signed 24-bit signed integer
270
const int IFIT_I32       =  0x10000;  // fits into signed 32-bit integer
271
const int IFIT_J32       =  0x20000;  // (-x) fits into signed 32-bit integer
272
const int IFIT_U32       =  0x40000;  // fits into unsigned 32-bit integer
273
const int IFIT_I32SHIFT  =  0x80000;  // fits into signed 32-bit integer with left shift
274
const int IFIT_I32SH32   = 0x100000;  // fits into 32-bit integer shifted left by 32
275
const int IFIT_J         =  (IFIT_J8 | IFIT_J16 | IFIT_J32); // (-x) fits better than x
276
const int FFIT_16       = 0x1000000;  // fits into normal half precision
277
const int FFIT_32       = 0x2000000;  // fits into normal single precision
278
const int FFIT_64       = 0x4000000;  // fits into double precision
279
const int IFIT_RELOC   = 0x10000000;  // relocation record needed
280
const int IFIT_LARGE   = 0x20000000;  // choose the larger size if uncertain. This input is used if optimization process has convergence problems
281
 
282
// values for immediate operand types
283
//const int OPI_INT4            =   1;  // int4
284
const int OPI_INT8            =   2;  // int8
285
const int OPI_INT16           =   3;  // int16
286
const int OPI_INT32           =   4;  // int32
287
const int OPI_INT64           =   5;  // int64
288
const int OPI_INT8SH          =   6;  // int8 << i
289
const int OPI_INT16SH         =   7;  // int16 << i
290
const int OPI_INT16SH16       =   8;  // int16 << 16
291
const int OPI_INT32SH32       =   9;  // int32 << 32
292
const int OPI_UINT8           =  18;  // uint8
293
const int OPI_UINT16          =  19;  // uint16
294
const int OPI_UINT32          =  20;  // uint32
295
const int OPI_UINT64          =  21;  // uint64
296
const int OPI_2INT8           =  24;  // int8+int8
297
const int OPI_INT886          =  25;  // int8+int8+int6
298
const int OPI_2INT16          =  26;  // int16+int16
299
const int OPI_INT1632         =  27;  // int16+int32
300
const int OPI_2INT32          =  28;  // int32+int32
301
const int OPI_INT1688         =  29;  // int16+int8+int8
302
const int OPI_INT8F           =  34;  // int8 converted to float
303
const int OPI_INT16F          =  35;  // int16 converted to float
304
const int OPI_FLOAT16         =  64;  // float16
305
const int OPI_FLOAT32         =  65;  // float32
306
const int OPI_FLOAT64         =  66;  // float64
307
const int OPI_IMPLICIT        =  99;  // implicit immediate operand (usually uint8)
308
const int OPI_OT              = 100;  // determined by operand type field
309
 
310
 
311
// struct SLine contains information about each line in the input file
312
struct SLine {
313
    uint16_t type;                // line type: LINE_DATADEF, etc
314
    uint16_t sectionType;         // section flags
315
    uint32_t beginPos;            // position in input file
316
    uint32_t firstToken;          // index to first token
317
    uint32_t numTokens;           // number of tokens in line
318
    uint32_t file;                // file of origin. (1 = source file, 2+ = include files, 0x1000+ = meta-generated lines)
319
    uint32_t linenum;             // line number in file of origin
320
};
321
 
322
// struct SToken is used for splitting each line into tokens
323
struct SToken {
324
    uint32_t type;                // Token type
325
    uint32_t id;                  // ID if known name or operator
326
    uint32_t pos;                 // File offset
327
    uint32_t stringLength;        // Length of token as string
328
    uint16_t priority;            // Priority if operator
329
    uint16_t vartype;             // 0: value not known, 3: int64, 5: double, 8: string
330
    uint32_t unused;
331
    union {                       // value if constant or assemble-time variable
332
        uint64_t u;
333
        int64_t  i;
334
        double   d;
335
        uint32_t w;
336
    } value;
337
};
338
 
339
// struct SOperator is used for list of operators
340
struct SOperator {
341
    char name[8];                 // name
342
    uint32_t id;                  // identifier
343
    uint32_t priority;            // priority if operator
344
};
345
 
346
// operator < for sorting operator list
347
static inline bool operator < (SOperator const & a, SOperator const & b) {
348
    return strcmp(a.name, b.name) < 0;
349
}
350
 
351
// struct SKeyword is used for list of keywords
352
struct SKeyword {
353
    char name[28];                // name
354
    uint32_t id;                  // identifier
355
};
356
 
357
// struct SExpression is used during assemble-time evaluation of expressions containing
358
// any type of operands: integer, float, string, registers, memory operands, options
359
struct SExpression {
360
    union {                       // immediate operand value
361
        int64_t  i;               // as signed
362
        uint64_t u;               // as unsigned
363
        double   d;               // as double
364
        uint32_t w;               // as unsigned 32 bit integer
365
    } value;
366
    int32_t  offset_mem;          // offset for memory operand
367
    int32_t  offset_jump;         // offset for jump
368
    uint32_t etype;               // flags for elements in expression: XPR_...
369
    uint32_t tokens;              // number of tokens used
370
    uint32_t sym1;                // first symbol of memory operand, indexed by namebuffer offset
371
    uint32_t sym2;                // reference symbol of memory operand, indexed by namebuffer offset
372
    uint32_t sym3;                // first symbol of immediate operand, indexed by namebuffer offset
373
    uint32_t sym4;                // reference symbol of immediate operand, indexed by namebuffer offset
374
    uint32_t sym5;                // symbol for jump target, indexed by namebuffer offset
375
    uint32_t instruction;         // instruction corresponding to operator
376
    uint8_t  optionbits;          // option bits or sign bits
377
    uint8_t  base;                // base register of memory operand    
378
    uint8_t  index;               // index register of memory operand
379
    uint8_t  length;              // length or broadcast register of memory operand
380
    int8_t   scale;               // scale factor for index register
381
    uint8_t  symscale1;           // scale factor for sym1-sym2    
382
    uint8_t  symscale3;           // scale factor for sym3-sym4
383
    uint8_t  mask;                // mask register
384
    uint8_t  reg1;                // first register operand
385
    uint8_t  reg2;                // second register operand
386
    uint8_t  reg3;                // third register operand   
387
    uint8_t  fallback;            // fallback register
388
};
389
 
390
 
391
// struct SCode is the result of interpreting a line of code containing an instruction
392
struct SCode : public SExpression {
393
    SFormat  const * formatp;     // instruction format. pointer to record in formatList in disassem1.cpp, or a copy of it
394
    uint32_t line;                // entry into lines buffer
395
    uint32_t section;             // code section
396
    uint32_t address;             // address relative to begin of section in current module
397
    uint32_t label;               // a code or data label, identified by an index into symbolNameBuffer (not an index into 'symbols' because this may change when new symbols are added)
398
    uint32_t dtype;               // data type. (TYP_INT8 etc.)
399
    uint32_t instr1;              // index to instruction in instructionlist
400
    uint32_t fitNum;              // indicates if immediate constant fits a certain representation (from fitInteger or fitFloat function)
401
    uint32_t fitAddr;             // indicates if relative address fits a certain number of bits
402
    uint32_t fitJump;             // indicates if relative jump offset fits a certain number of bits
403
    uint8_t  dest;                // destination register (2 = memory destination)
404
    uint8_t  numOp;               // number of source operands
405
    uint8_t  size;                // size of instruction. minimum size if actual size depends on unresolved cross references
406
    uint8_t  sizeUnknown;         // actual size may be up to this value bigger
407
    uint8_t  category;            // instruction category
408
};
409
 
410
 
411
// struct SBlock is used for tracking {} code blocks
412
struct SBlock  {
413
    uint32_t blockType;           // block type. see definitions of HL_FUNC etc. in assem5.cpp
414
    uint32_t blockNumber;         // sequential number used in label names
415
    uint32_t startBracket;        // token of start '{'
416
    uint32_t jumpLabel;           // target label for jump, else, or loop
417
    uint32_t breakLabel;          // target label for break statement. -1 if break is possible but label not yet defined
418
    uint32_t continueLabel;       // target label for continue statement. -1 if continue is possible but label not yet defined
419
    uint32_t codeBuffer2index;    // index of entry in codeBuffer2
420
    uint32_t codeBuffer2num;      // number of instruction codes in codeBuffer2
421
};
422
 
423
// combine contents of two expressions
424
static inline SExpression operator | (SExpression const & exp1, SExpression const & exp2) {
425
    SExpression expr;
426
    for (uint32_t i = 0; i < sizeof(SExpression) / sizeof(uint64_t); i++) {
427
        (&expr.value.u)[i] = (&exp1.value.u)[i] | (&exp2.value.u)[i];
428
    }
429
    return expr;
430
}
431
 
432
static inline SCode operator | (SCode const & code1, SExpression const & exp2) {
433
    SCode code0 = code1;
434
    for (uint32_t i = 0; i < sizeof(SExpression) / sizeof(uint64_t); i++) {
435
        (&code0.value.u)[i] = (&code1.value.u)[i] | (&exp2.value.u)[i];
436
    }
437
    return code0;
438
}
439
 
440
// find the smallest representation that the floating point operand fits into
441
int fitFloat(double x);
442
 
443
// insert memory operand into code structure
444
void insertMem(SCode & code, SExpression & expr);
445
 
446
// insert everything from expression to code structure, OR'ing all bits
447
void insertAll(SCode & code, SExpression & expr);
448
 
449
// operator < for sorting keyword list
450
static inline bool operator < (SKeyword const & a, SKeyword const & b) {
451
    // case insensitive compare. This function is not standardized. make my own:
452
    return strncasecmp_(a.name, b.name, 1000) < 0;
453
 
454
#if defined (_MSC_VER)
455
    //return _stricmp(a.name, b.name) < 0;    // microsoft
456
#else
457
    //return strcasecmp(a.name, b.name) < 0;  // unix
458
#endif
459
 
460
}
461
 
462
// redefine symbol structure sorted by name
463
struct ElfFWC_Sym2 : public ElfFwcSym {
464
};
465
 
466
 
467
static inline bool operator < (ElfFWC_Sym2 const & a, ElfFWC_Sym2 const & b) {
468
    return strcmp(symbolNameBuffer.getString(a.st_name), symbolNameBuffer.getString(b.st_name)) < 0;
469
}
470
 
471
static inline bool operator == (ElfFWC_Sym2 const & a, ElfFWC_Sym2 const & b) {
472
    return strcmp(symbolNameBuffer.getString(a.st_name), symbolNameBuffer.getString(b.st_name)) == 0;
473
}
474
 
475
// structure in list of assembly errors
476
struct SAssemError {
477
    uint32_t pos;                                // position in input file
478
    uint32_t stringLength;                       // length of token string
479
    uint32_t file;                               // File where error was detected
480
    uint16_t num;                                // Error id
481
    uint16_t pass;                               // Pass during which error occurred
482
};
483
 
484
class CAssembler;                                // Forward definition
485
 
486
// class for reporting errors in assembly file
487
class CAssemErrors {
488
public:
489
    CAssemErrors();
490
    void report(uint32_t position, uint32_t stringLength, uint32_t num); // Report an error
491
    void report(SToken const & token);           // Report an error, pointing to a specific token
492
    void reportLine(uint32_t num);               // Report an error in current line
493
    void setOwner(CAssembler * a);               // Give access to CAssembler
494
    uint32_t numErrors();                        // Return number of errors
495
    bool tooMany();                              // true if too many errors
496
    void outputErrors();                         // Write all errors to stderr
497
protected:
498
    CAssembler * owner;
499
    CDynamicArray<SAssemError>list;              // List of errors
500
    uint32_t maxErrors;                          // Maximum number of errors to report
501
};
502
 
503
 
504
// class CDisassembler handles disassembly of ForwardCom ELF file
505
class CAssembler : public CFileBuffer {
506
public:
507
    CAssembler();                                // Constructor
508
    void go();
509
protected:
510
    friend class CAssemErrors;                   // This class handles error messages
511
    uint32_t iInstr;                             // Position of current instruction relative to section start
512
    uint32_t instrLength;                        // Length of current instruction, in 32-bit words
513
    uint32_t operandType;                        // Operand type of current instruction
514
    uint32_t format;                             // Format of current instruction
515
    uint64_t variant;                            // Template variant and options
516
    int64_t  value0;                             // original value of immediate operand   
517
    uint32_t tokenB;                             // index to first token in current line
518
    uint32_t tokenN;                             // number of tokens in current line
519
    uint32_t dataType;                           // data type for current instruction
520
    uint32_t section;                            // Current section
521
    uint32_t sectionFlags;                       // current section information flags
522
    uint32_t linei;                              // index to current line
523
    uint32_t filei;                              // index to current input file
524
    uint32_t pass;                               // what pass are we in
525
    uint32_t iLoop;                              // index of current loop statement
526
    uint32_t iIf;                                // index of current 'if' statement
527
    uint32_t iSwitch;                            // index of current 'switch' statement    
528
    uint32_t numSwitch;                          // total number of 'switch' statements
529
    bool     lineError;                          // error in current line. stop interpreting
530
    uint64_t code_size;                          // codesize option determines code address sizes
531
    uint64_t data_size;                          // datasize option determines data address sizes
532
    STemplate const * pInstr;                    // Pointer to current instruction code
533
    SInstruction2 const * iRecord;               // Pointer to instruction table entry
534
    SFormat const * fInstr;                      // Format details of current instruction code
535
    CELF outFile;                                // Output file
536
    CDynamicArray<SToken> tokens;                // List of tokens
537
    CDynamicArray<SLine> lines;                  // Information about each line of the input file
538
    CDynamicArray<SInstruction> instructionlist; // List of instruction set, unsorted
539
    CDynamicArray<SInstruction> instructionlistNm;// List of instruction set, sorted by name
540
    CDynamicArray<SInstruction3> instructionlistId; // List of instruction set, sorted by id
541
    CDynamicArray<SOperator> operators;          // List of operators
542
    CDynamicArray<SKeyword> keywords;            // List of keywords
543
    CDynamicArray<ElfFWC_Sym2> symbols;          // List of symbols
544
    CDynamicArray<ElfFwcReloc> relocations;     // List of relocations
545
    CDynamicArray<uint8_t> brackets;             // Stack of nested brackets during evaluation of expression
546
    CDynamicArray<SCode> codeBuffer;             // Coded instructions
547
    CDynamicArray<SCode> codeBuffer2;            // Temporary storage of instructions for loops and switch statements
548
    CDynamicArray<ElfFwcShdr> sectionHeaders;    // Section headers
549
    CDynamicArray<SFormat> formatList3;          // Subset of formatList for multiformat instruction formats
550
    CDynamicArray<SFormat> formatList4;          // Subset of formatList for jump instruction formats
551
    CDynamicArray<SBlock>  hllBlocks;            // Tracking of {} blocks    
552
    CDynamicArray<SExpression> expressions;      // Expressions saved as assemble-time symbols    
553
    CTextFileBuffer stringBuffer;                // Buffer for assemble-time string variables
554
    CMetaBuffer<CMemoryBuffer> dataBuffers;      // databuffer for each section
555
    CAssemErrors errors;                         // Error reporting
556
    void initializeWordLists();                  // Initialize and sort instruction list, operator list, and keyword list
557
    void feedBackText1();                        // write feedback text on stdout
558
    void pass1();                                // Split input file into lines and tokens. Handle preprocessing directives. Find symbol definitions
559
    void interpretSectionDirective();            // Interpret section directive during pass 2 or 3
560
    void interpretFunctionDirective();           // Interpret function directive during pass 2 or 3
561
    void interpretEndDirective();                // Interpret section or function end directive during pass 2 or 3
562
    void interpretOptionsLine();                 // Interpret line specifying options
563
    uint32_t addSymbol(ElfFWC_Sym2 & sym);       // Add a symbol to symbols list
564
    uint32_t findSymbol(uint32_t name);          // Find symbol by index into symbolNameBuffer
565
    uint32_t findSymbol(const char * name, uint32_t len); // Find symbol by name with specified length
566
    void pass2();                                // A. Handle metaprogramming directives
567
                                                 // B. Classify lines
568
                                                 // C. Identify symbol names, sections, labels, functions 
569
    void interpretExternDirective();             // Interpret extern directive during pass 2
570
    void interpretPublicDirective();             // Interpret public directive during pass 2
571
    void interpretLabel(uint32_t tok);           // Interpret code or data label during pass 2
572
    void interpretVariableDefinition1();         // interpret assembly style variable definition
573
    void interpretVariableDefinition2();         // interpret C style variable definition
574
    void determineLineType();                    // check if line is code or data
575
    void interpretAlign();                       // interpret code or data alignment directive
576
    void interpretMetaDefinition();              // Interpret line beginning with '%' containing meta code
577
    void replaceKnownNames();                    // Replace known symbol names with symbol references and meta variables with their value
578
    SExpression expression(uint32_t tok1, uint32_t ntok, uint32_t option); // Interpret and evaluate expression
579
    SExpression symbol2expression(uint32_t symi); // make expression out of symbol
580
    SExpression op1minus(SExpression & exp1);    // Interpret -(A+B), etc.
581
    SExpression op2(uint32_t op, SExpression & exp1, SExpression & exp2); // Interpret dyadic expression with any type of operands
582
    SExpression op2Int(uint32_t op, SExpression const & exp1, SExpression const & exp2); // Interpret dyadic expression with integer operands
583
    SExpression op2Float(uint32_t op, SExpression & exp1, SExpression & exp2); // Interpret dyadic expression with floating point operands
584
    SExpression op2String(uint32_t op, SExpression const & exp1, SExpression const & exp2); // Interpret dyadic expression with string operands
585
    SExpression op2Registers(uint32_t op, SExpression const & exp1, SExpression const & exp2); // Interpret dyadic expression with register operands
586
    SExpression op2Memory(uint32_t op, SExpression & exp1, SExpression & exp2); // Interpret dyadic expression with memory operands
587
    SExpression op3(uint32_t tok1, uint32_t toklow, uint32_t tokcolon, uint32_t maxtok, uint32_t options); // Interpreted triadic expression exp1 ? exp2 : exp3 at the indicated positions
588
    void assignMetaVariable(uint32_t symi, SExpression & expr, uint32_t typetoken); // define or modify assemble-time constant or variable
589
    void pass3();                                // Generate code and data
590
    void makeFormatLists();                      // extract subsets of formatList into formatList3 and formatList4
591
    void interpretCodeLine();                    // Interpret a line defining code
592
    int  fitCode(SCode & code);                  // find an instruction variant that fits the code
593
    bool instructionFits(SCode const & code, SCode & codeTemp, uint32_t ii); // check if instruction fits into specified format
594
    bool jumpInstructionFits(SCode const & code, SCode & codeTemp, uint32_t ii); // check if jump instruction fits into specified format
595
    int  fitConstant(SCode & code);              // check how many bits are needed to contain immediate constant in an instruction.
596
    int  fitAddress(SCode & code);               // check how many bits are needed to contain relative address in an instruction.
597
    void checkCode1(SCode & code);               // eheck code for correctness before fitting a format, and fix some code details
598
    void checkCode2(SCode & code);               // eheck register types etc. after fitting a format, and finish code details
599
    uint32_t checkCodeE(SCode & code);           // find reason why no format fits, and return error number
600
    void optimizeCode(SCode & code);             // optimize instruction. replace by more efficient instruction if possible
601
    void pass4();                                // Resolve symbol addresses and cross references, optimize forward references
602
    void pass5();                                // Make binary file
603
    void copySections();                         // copy sections to outFile
604
    void copySymbols();                          // copy symbols to outFile
605
    //void removePrivateSymbols();               // remove local symbols and adjust relocation records with new symbol indexes
606
    void makeListFile();                         // make output listing
607
    int64_t calculateMemoryOffset(SCode & code); // calculate memory address possibly involving symbol. generate relocation if necessary
608
    int64_t calculateJumpOffset(SCode & code);   // calculate jump offset possibly involving symbol. generate relocation if necessary
609
    int64_t calculateConstantOperand(SExpression & expr, uint64_t address, uint32_t fieldSize); // calculate constant or immediate operand possibly involving symbol. generate relocation if necessary
610
    void makeBinaryCode();                       // make binary data for code sections
611
    void makeBinaryData();                       // make binary data for data sections
612
    void makeBinaryRelocations();                // put relocation records in output file
613
    void showTokens();                           // Show all tokens. For debugging only
614
    void showSymbols();                          // Show all symbols. For debugging only
615
    void interpretHighLevelStatement();          // if, else, switch, for, do, while statements    
616
    void interpretEndBracket();                  // finish {} block
617
    void codeIf();                               // Interpret if statement in assembly code
618
    void codeIf2();                              // Finish if statement at end bracket
619
    void codeWhile();                            // Interpret while loop in assembly code
620
    void codeWhile2();                           // Finish while-loop at end bracket
621
    void codeDo();                               // Interpret do-while loop in assembly code
622
    void codeDo2();                              // Finish do-while loop at end bracket
623
    void codeFor();                              // Interpret for-loop in assembly code
624
    void codeFor2();                             // Finish for-loop at end bracket
625
    void codeForIn();                            // Interpret for-in vector loop in assembly code
626
    void codeForIn2();                           // Finish for-in vector loop in assembly code
627
    void codeSwitch();                           // Interpret switch statement in assembly code
628
    void codeCase();                             // Interpret switch case label in assembly code
629
    void codeSwitch2();                          // Finish switch statement at end bracket
630
    void codeBreak();                            // Interpret break or continue statement in assembly code
631
    uint32_t findBreakTarget(uint32_t k);        // Find or make the target symbol of a break or continue statement
632
    uint32_t makeLabelSymbol(const char * name); // Make a symbol for branch label etc., address not known yet
633
    bool mergeJump(SCode & code2);               // Merge jump instruction with preceding arithmetic instruction
634
    uint32_t hasJump(uint32_t line);             // check if line contains unconditional direct jump
635
    void interpretCondition(SCode & code);       // interpret condition in if(), while(), and for(;;) statements
636
    void codePush();                             // push register on stack. (may be replaced by macros later)
637
    void codePop();                              // pop register from stack. (may be replaced by macros later)
638
};

powered by: WebSVN 2.1.0

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