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 |
|
|
};
|