1 |
|
|
/* |
2 |
|
|
Copyright 2025 Joel Svensson svenssonjoel@yahoo.se |
3 |
|
|
|
4 |
|
|
This program is free software: you can redistribute it and/or modify |
5 |
|
|
it under the terms of the GNU General Public License as published by |
6 |
|
|
the Free Software Foundation, either version 3 of the License, or |
7 |
|
|
(at your option) any later version. |
8 |
|
|
|
9 |
|
|
This program is distributed in the hope that it will be useful, |
10 |
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 |
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
12 |
|
|
GNU General Public License for more details. |
13 |
|
|
|
14 |
|
|
You should have received a copy of the GNU General Public License |
15 |
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>. |
16 |
|
|
*/ |
17 |
|
|
|
18 |
|
|
|
19 |
|
|
#include <extensions.h> |
20 |
|
|
#include <lbm_image.h> |
21 |
|
|
#include <heap.h> |
22 |
|
|
#include <env.h> |
23 |
|
|
#include <lbm_flat_value.h> |
24 |
|
|
#include <eval_cps.h> |
25 |
|
|
#include <extensions.h> |
26 |
|
|
|
27 |
|
|
// Assumptions about the image memory: |
28 |
|
|
// * It is part of the address space. |
29 |
|
|
// * Image is always available at the same address (across reboots) |
30 |
|
|
// * It is a write-once memory. |
31 |
|
|
// * Can be cleared in its entirety. |
32 |
|
|
// * Can check on a byte-level is "is-writable" (has a known initial state when cleared) |
33 |
|
|
|
34 |
|
|
// Details |
35 |
|
|
// * @const_start @const_end is tricky. |
36 |
|
|
// * Constant heap is needed because of small amount of RAM. |
37 |
|
|
// * Arbitrary pointers will be tricky. |
38 |
|
|
|
39 |
|
|
// Want to be able to build an image incrementally. |
40 |
|
|
// Can @const_start @const_end be used in conjuction with a |
41 |
|
|
// more exlicit image manipulation subsystem. |
42 |
|
|
|
43 |
|
|
//TBD: |
44 |
|
|
// * does an image contain running threads ? (I would prefer if no) |
45 |
|
|
// instead there is a startup-entry that represents some code that will |
46 |
|
|
// be executed after setting up an image. |
47 |
|
|
// This startup-entry can spawn threads and initialize resources. |
48 |
|
|
// * Will we have a heap-image or will all bindings move into the const heap. |
49 |
|
|
|
50 |
|
|
// FEB 26: |
51 |
|
|
// -- There will be no "heap-image" or "memory-image" |
52 |
|
|
// Just flattened and stored bindings from the environment (which is as good but likely smaller). |
53 |
|
|
// -- There will be an image of the const-heap. in fact the const heap lives in the image always. |
54 |
|
|
// A bit problematic with building on image incrementally as it is in flash and the contents cannot be changed. |
55 |
|
|
// Contents can be added though! (keep track of const-heap write-ptr is an issue) |
56 |
|
|
// -- Maybe we should implement image for a read-write memory and then make the flash situation a special case? |
57 |
|
|
// -- Maybe size fields should always be in bytes. |
58 |
|
|
// -- TODO: a flatten function that flattens a value directly to flash and also does not flatten things that are |
59 |
|
|
// already in flash, but rather then just refers to them. |
60 |
|
|
|
61 |
|
|
// FEB 27: |
62 |
|
|
// -- Symbol numbering will be an issue. |
63 |
|
|
// * Store the symboltable in the image and restore it on boot. |
64 |
|
|
// * Names already in flash can be refered to. |
65 |
|
|
// * Names in ram can be copied. |
66 |
|
|
// * Entire subtable may already be in flash - leave in place and refer to it. |
67 |
|
|
// -- loading an image and then adding to it can be tricky to make possible. |
68 |
|
|
// * const-heap write pointer needs to be stored. (but if it is stored then it cannot be changed) |
69 |
|
|
// Could allow multiple "const-heap-write-pointer" fields in the image and use the one that appears last... |
70 |
|
|
// * Symboltable could be created incrementally in a similar way. Append later symbol_table data fields |
71 |
|
|
// to the previously loaded. |
72 |
|
|
|
73 |
|
|
// FEB 28: |
74 |
|
|
// -- Symbol numbering problem. The structure of the symboltable may |
75 |
|
|
// need to change. It is currently impossible to append a symbol list stored |
76 |
|
|
// in flash to the global symbol table. A richer structure is needed. |
77 |
|
|
// -- The symbols in the SYMTAB can all be in flash (all in the image) and |
78 |
|
|
// all name strings can be written to flash as well. |
79 |
|
|
// * May be easiest if names go to the flash heap (as it is now) |
80 |
|
|
// and table entries are a tagged field in the image (1 extra byte per symbol...) |
81 |
|
|
// * Means the image must be initialized (to a degree) before symbols are created. |
82 |
|
|
|
83 |
|
|
// MARCH 1: |
84 |
|
|
// -- Symbols are added to and restored from the image. |
85 |
|
|
// -- lbm_add_symbol_const, still creates a lbm_memory list structure. |
86 |
|
|
// Const symbols should also be stored into the image and add_symbol_const |
87 |
|
|
// should check and reuse stored symbol id. |
88 |
|
|
// Check order of initialization to see how easy this is to fix. |
89 |
|
|
|
90 |
|
|
// Offline image tools |
91 |
|
|
// - Image compaction: remove overwrite fields and compact the image. |
92 |
|
|
// - Change of base address: relabel all memory accesses. |
93 |
|
|
// - ... |
94 |
|
|
|
95 |
|
|
|
96 |
|
|
// MARCH 5 |
97 |
|
|
// -- Can constants (anything on const heap) contain references into non-constant heap? |
98 |
|
|
// - I think not, but should verify this. |
99 |
|
|
// - eval_cps move_to_flash performs a deep copy into flash. |
100 |
|
|
|
101 |
|
|
// Endianess woes... |
102 |
|
|
// - little endian least-significant byte at least address |
103 |
|
|
// - big endian most-significant byte at least address |
104 |
|
|
// - all platforms we target currently are little-endian |
105 |
|
|
// |
106 |
|
|
// 0x11223344 |
107 |
|
|
// | | | '--- [44] addr |
108 |
|
|
// | | '----- [33] addr + 1 |
109 |
|
|
// | '------- [22] addr + 2 |
110 |
|
|
// '--------- [11] addr + 3 |
111 |
|
|
// |
112 |
|
|
// Images are going to be mainly little endian. (what endianess does flatvalues use? I think BE) |
113 |
|
|
|
114 |
|
|
// constant heap should be 4byte aligned so that there are 2 unused low end bits |
115 |
|
|
// in all cell-pointers into constant heap. |
116 |
|
|
|
117 |
|
|
// March 8 |
118 |
|
|
// -- flattening lead to duplication of shared nodes. |
119 |
|
|
// if a = '(1 2 3) and b = (cons 4 a) and c = (cons 5 a) |
120 |
|
|
// then the result of flattening a b c each contains a full copy of a. |
121 |
|
|
// -- flattening a value that in turn points to a constant value, duplicates |
122 |
|
|
// the constant value. |
123 |
|
|
|
124 |
|
|
// TODO: Put more info into the IMAGE_INITIALIZED FIELD |
125 |
|
|
// - 32/64 bit etc |
126 |
|
|
|
127 |
|
|
#ifdef LBM64 |
128 |
|
|
#define IMAGE_INITIALIZED (uint32_t)0xBEEF4001 // [ 0xBEEF4001 ] |
129 |
|
|
#else |
130 |
|
|
#define IMAGE_INITIALIZED (uint32_t)0xBEEF2001 // [ 0xBEEF2001 ] |
131 |
|
|
#endif |
132 |
|
|
// Address downwards -> |
133 |
|
|
#define CONSTANT_HEAP_IX (uint32_t)0x02 // [ 0x02 | uint32] |
134 |
|
|
#define BINDING_CONST (uint32_t)0x03 // [ 0x03 | key | lbm_uint ] |
135 |
|
|
#define BINDING_FLAT (uint32_t)0x04 // [ 0x04 | size | key | flatval ] |
136 |
|
|
#define STARTUP_ENTRY (uint32_t)0x05 // [ 0x05 | symbol ]) |
137 |
|
|
#define SYMBOL_ENTRY (uint32_t)0x06 // [ 0x06 | NEXT_PTR | ID | NAME PTR ] // symbol_entry with highest address is root. |
138 |
|
|
#define SYMBOL_LINK_ENTRY (uint32_t)0x07 // [ 0x07 | C_LINK_PTR | NEXT_PTR | ID | NAME PTR ] |
139 |
|
|
#define EXTENSION_TABLE (uint32_t)0x08 // [ 0x08 | NUM | EXT ...] |
140 |
|
|
#define VERSION_ENTRY (uint32_t)0x09 // [ 0x09 | size | string ] |
141 |
|
|
// Size is in number of 32bit words, even on 64 bit images. |
142 |
|
|
|
143 |
|
|
// To be able to work on an image incrementally (even though it is not recommended) |
144 |
|
|
// many fields are allowed to be duplicated and the later ones have priority |
145 |
|
|
// over earlier ones. |
146 |
|
|
|
147 |
|
|
|
148 |
|
|
#define DOWNWARDS true |
149 |
|
|
#define UPWARDS false |
150 |
|
|
|
151 |
|
|
static lbm_image_write_fun image_write = NULL; |
152 |
|
|
|
153 |
|
|
static uint32_t *image_address = NULL; |
154 |
|
|
static int32_t write_index = 0; |
155 |
|
|
static uint32_t image_size = 0; |
156 |
|
|
static bool image_has_extensions = false; |
157 |
|
|
static char* image_version = NULL; |
158 |
|
|
|
159 |
|
|
uint32_t *lbm_image_get_image(void) { |
160 |
|
|
return image_address; |
161 |
|
|
} |
162 |
|
|
|
163 |
|
|
uint32_t lbm_image_get_size(void) { |
164 |
|
|
return image_size; |
165 |
|
|
} |
166 |
|
|
|
167 |
|
934148 |
int32_t lbm_image_get_write_index(void) { |
168 |
|
934148 |
return write_index; |
169 |
|
|
} |
170 |
|
|
|
171 |
|
|
bool lbm_image_has_extensions(void) { |
172 |
|
|
return image_has_extensions; |
173 |
|
|
} |
174 |
|
|
|
175 |
|
87696 |
uint32_t read_u32(int32_t index) { |
176 |
|
87696 |
return *((uint32_t*)(image_address + index)); |
177 |
|
|
} |
178 |
|
|
|
179 |
|
|
uint64_t read_u64(int32_t index) { |
180 |
|
|
// image_addres is an u32 ptr. so addr + i is a step of i * 4 bytes |
181 |
|
|
return *((uint64_t*)(image_address + index)); |
182 |
|
|
} |
183 |
|
|
|
184 |
|
4714836 |
bool write_u32(uint32_t w, int32_t *i, bool direction) { |
185 |
|
4714836 |
bool r = image_write(w, *i, false); |
186 |
✓✓ |
4714836 |
(*i) += direction ? -1 : 1; |
187 |
|
4714836 |
return r; |
188 |
|
|
} |
189 |
|
|
|
190 |
|
|
|
191 |
|
|
bool write_u64(uint64_t dw, int32_t *i, bool direction) { |
192 |
|
|
uint32_t *words = (uint32_t*)&dw; |
193 |
|
|
|
194 |
|
|
// downwards ... hw lw |
195 |
|
|
// ix ix-1 |
196 |
|
|
// upwards hw lw ... |
197 |
|
|
// ix+1 ix |
198 |
|
|
|
199 |
|
|
// true = downwards |
200 |
|
|
|
201 |
|
|
bool r = true; |
202 |
|
|
if (direction) { |
203 |
|
|
r = r && write_u32(words[1], i, direction); |
204 |
|
|
r = r && write_u32(words[0], i, direction); |
205 |
|
|
} else { |
206 |
|
|
r = r && write_u32(words[0], i, direction); |
207 |
|
|
r = r && write_u32(words[1], i, direction); |
208 |
|
|
} |
209 |
|
|
return r; |
210 |
|
|
} |
211 |
|
|
|
212 |
|
|
// fv_write function write values as big endian. |
213 |
|
|
|
214 |
|
|
uint32_t fv_buf_ix = 0; |
215 |
|
|
uint8_t fv_buf[4] = {0}; |
216 |
|
|
bool fv_write_u8(uint8_t b) { |
217 |
|
|
bool r = true; |
218 |
|
|
if (fv_buf_ix >= 4) { |
219 |
|
|
r = write_u32(((uint32_t*)fv_buf)[0], &write_index, UPWARDS); |
220 |
|
|
memset(fv_buf,0,4); |
221 |
|
|
fv_buf_ix = 0; |
222 |
|
|
} |
223 |
|
|
fv_buf[fv_buf_ix] = b; |
224 |
|
|
fv_buf_ix++; |
225 |
|
|
return r; |
226 |
|
|
} |
227 |
|
|
|
228 |
|
|
bool fv_write_flush(void) { |
229 |
|
|
if (fv_buf_ix == 0) return true; |
230 |
|
|
else { |
231 |
|
|
bool r = write_u32(((uint32_t*)fv_buf)[0], &write_index, UPWARDS);; |
232 |
|
|
fv_buf_ix = 0; |
233 |
|
|
memset(fv_buf,0,4); |
234 |
|
|
return r; |
235 |
|
|
} |
236 |
|
|
} |
237 |
|
|
|
238 |
|
|
bool fv_write_u32(uint32_t w) { |
239 |
|
|
uint8_t * bytes = (uint8_t*)&w; |
240 |
|
|
return |
241 |
|
|
fv_write_u8(bytes[3]) && |
242 |
|
|
fv_write_u8(bytes[2]) && |
243 |
|
|
fv_write_u8(bytes[1]) && |
244 |
|
|
fv_write_u8(bytes[0]); |
245 |
|
|
} |
246 |
|
|
|
247 |
|
|
bool fv_write_u64(uint64_t dw) { |
248 |
|
|
uint8_t * bytes = (uint8_t*)&dw; |
249 |
|
|
return |
250 |
|
|
fv_write_u8(bytes[7]) && |
251 |
|
|
fv_write_u8(bytes[6]) && |
252 |
|
|
fv_write_u8(bytes[5]) && |
253 |
|
|
fv_write_u8(bytes[4]) && |
254 |
|
|
fv_write_u8(bytes[3]) && |
255 |
|
|
fv_write_u8(bytes[2]) && |
256 |
|
|
fv_write_u8(bytes[1]) && |
257 |
|
|
fv_write_u8(bytes[0]); |
258 |
|
|
} |
259 |
|
|
|
260 |
|
|
|
261 |
|
2207070 |
bool write_lbm_uint(lbm_uint ptr_val, int32_t *i, bool direction) { |
262 |
|
|
#ifdef LBM64 |
263 |
|
|
return write_u64(ptr_val, i, direction); |
264 |
|
|
#else |
265 |
|
2207070 |
return write_u32(ptr_val, i, direction); |
266 |
|
|
#endif |
267 |
|
|
} |
268 |
|
|
|
269 |
|
|
bool write_lbm_value(lbm_value v, int32_t *i, bool direction) { |
270 |
|
|
#ifdef LBM64 |
271 |
|
|
return write_u64(v, i, direction); |
272 |
|
|
#else |
273 |
|
|
return write_u32(v, i, direction); |
274 |
|
|
#endif |
275 |
|
|
} |
276 |
|
|
|
277 |
|
|
// //////////////////////////////////////////////////////////// |
278 |
|
|
// Flatten a value into image |
279 |
|
|
|
280 |
|
|
// TODO: Consants things that are stored in the image |
281 |
|
|
// does not need to be flattened. Could refer to these by |
282 |
|
|
// reference. Some new kinds of flat values needs to be added |
283 |
|
|
// for this referencing to work. |
284 |
|
|
|
285 |
|
|
// TODO: Symbols in a flat_value in an image can be stored as |
286 |
|
|
// its numerical representation rather than its string rep. |
287 |
|
|
|
288 |
|
|
static bool i_f_cons(void ) { |
289 |
|
|
return fv_write_u8(S_CONS); |
290 |
|
|
} |
291 |
|
|
|
292 |
|
|
static bool i_f_lisp_array(uint32_t size) { |
293 |
|
|
// arrays are smaller than 2^32 elements long |
294 |
|
|
bool r = fv_write_u8(S_LBM_LISP_ARRAY); |
295 |
|
|
r = r && fv_write_u32(size); |
296 |
|
|
return r; |
297 |
|
|
} |
298 |
|
|
|
299 |
|
|
static bool i_f_sym(lbm_value sym) { |
300 |
|
|
lbm_uint sym_id = lbm_dec_sym(sym); |
301 |
|
|
bool r = fv_write_u8(S_SYM_VALUE); |
302 |
|
|
#ifndef LBM64 |
303 |
|
|
r = r && fv_write_u32(sym_id); |
304 |
|
|
#else |
305 |
|
|
r = r && fv_write_u64(sym_id); |
306 |
|
|
#endif |
307 |
|
|
return r; |
308 |
|
|
} |
309 |
|
|
|
310 |
|
|
static bool i_f_i(lbm_int i) { |
311 |
|
|
bool res = true; |
312 |
|
|
#ifndef LBM64 |
313 |
|
|
res = res && fv_write_u8(S_I28_VALUE); |
314 |
|
|
res = res && fv_write_u32((uint32_t)i); |
315 |
|
|
#else |
316 |
|
|
res = res && fv_write_u8(S_I56_VALUE); |
317 |
|
|
res = res && fv_write_u64((uint64_t)i); |
318 |
|
|
#endif |
319 |
|
|
return res; |
320 |
|
|
} |
321 |
|
|
|
322 |
|
|
static bool i_f_u(lbm_uint u) { |
323 |
|
|
bool res = true; |
324 |
|
|
#ifndef LBM64 |
325 |
|
|
res = res && fv_write_u8(S_U28_VALUE); |
326 |
|
|
res = res && fv_write_u32((uint32_t)u); |
327 |
|
|
#else |
328 |
|
|
res = res && fv_write_u8(S_U56_VALUE); |
329 |
|
|
res = res && fv_write_u64((uint64_t)u); |
330 |
|
|
#endif |
331 |
|
|
return res; |
332 |
|
|
} |
333 |
|
|
|
334 |
|
|
static bool i_f_b(uint8_t b) { |
335 |
|
|
bool res = true; |
336 |
|
|
res = res && fv_write_u8(S_BYTE_VALUE); |
337 |
|
|
res = res && fv_write_u8(b); |
338 |
|
|
return res; |
339 |
|
|
} |
340 |
|
|
|
341 |
|
|
static bool i_f_i32(int32_t w) { |
342 |
|
|
bool res = true; |
343 |
|
|
res = res && fv_write_u8(S_I32_VALUE); |
344 |
|
|
res = res && fv_write_u32((uint32_t)w); |
345 |
|
|
return res; |
346 |
|
|
} |
347 |
|
|
|
348 |
|
|
static bool i_f_u32(uint32_t w) { |
349 |
|
|
bool res = true; |
350 |
|
|
res = res && fv_write_u8(S_U32_VALUE); |
351 |
|
|
res = res && fv_write_u32(w); |
352 |
|
|
return res; |
353 |
|
|
} |
354 |
|
|
|
355 |
|
|
static bool i_f_float(float f) { |
356 |
|
|
bool res = true; |
357 |
|
|
res = res && fv_write_u8(S_FLOAT_VALUE); |
358 |
|
|
uint32_t u; |
359 |
|
|
memcpy(&u, &f, sizeof(uint32_t)); |
360 |
|
|
res = res && fv_write_u32((uint32_t)u); |
361 |
|
|
return res; |
362 |
|
|
} |
363 |
|
|
|
364 |
|
|
static bool i_f_double(double d) { |
365 |
|
|
bool res = true; |
366 |
|
|
res = res && fv_write_u8(S_DOUBLE_VALUE); |
367 |
|
|
uint64_t u; |
368 |
|
|
memcpy(&u, &d, sizeof(uint64_t)); |
369 |
|
|
res = res && fv_write_u64(u); |
370 |
|
|
return res; |
371 |
|
|
} |
372 |
|
|
|
373 |
|
|
static bool i_f_i64(int64_t w) { |
374 |
|
|
bool res = true; |
375 |
|
|
res = res && fv_write_u8(S_I64_VALUE); |
376 |
|
|
res = res && fv_write_u64((uint64_t)w); |
377 |
|
|
return res; |
378 |
|
|
} |
379 |
|
|
|
380 |
|
|
static bool i_f_u64(uint64_t w) { |
381 |
|
|
bool res = true; |
382 |
|
|
res = res && fv_write_u8(S_U64_VALUE); |
383 |
|
|
res = res && fv_write_u64(w); |
384 |
|
|
return res; |
385 |
|
|
} |
386 |
|
|
|
387 |
|
|
// num_bytes is specifically an uint32_t |
388 |
|
|
static bool i_f_lbm_array(uint32_t num_bytes, uint8_t *data) { |
389 |
|
|
bool res = fv_write_u8(S_LBM_ARRAY); |
390 |
|
|
res = res && fv_write_u32(num_bytes); |
391 |
|
|
if (res) { |
392 |
|
|
for (uint32_t i = 0; i < num_bytes; i ++ ) { |
393 |
|
|
if (!fv_write_u8(data[i])) return false; |
394 |
|
|
} |
395 |
|
|
} |
396 |
|
|
return res; |
397 |
|
|
} |
398 |
|
|
|
399 |
|
|
|
400 |
|
|
static void size_acc(lbm_value v, void *acc) { |
401 |
|
|
int32_t *s = (int32_t*)acc; |
402 |
|
|
|
403 |
|
|
lbm_uint t = lbm_type_of(v); |
404 |
|
|
|
405 |
|
|
if (t >= LBM_POINTER_TYPE_FIRST && t < LBM_POINTER_TYPE_LAST) { |
406 |
|
|
t = t & ~(LBM_PTR_TO_CONSTANT_BIT); |
407 |
|
|
} |
408 |
|
|
|
409 |
|
|
if (lbm_is_ptr(v) && (v & LBM_PTR_TO_CONSTANT_BIT)) { |
410 |
|
|
*s += (int32_t)sizeof(lbm_uint) + 1; |
411 |
|
|
return; |
412 |
|
|
} |
413 |
|
|
|
414 |
|
|
switch (t) { |
415 |
|
|
case LBM_TYPE_CONS: |
416 |
|
|
*s += 1; |
417 |
|
|
break; |
418 |
|
|
case LBM_TYPE_LISPARRAY: |
419 |
|
|
*s += 4 + 1; |
420 |
|
|
break; |
421 |
|
|
case LBM_TYPE_BYTE: |
422 |
|
|
*s += 2; |
423 |
|
|
break; |
424 |
|
|
case LBM_TYPE_U: |
425 |
|
|
*s += (int32_t)sizeof(lbm_uint) + 1; |
426 |
|
|
break; |
427 |
|
|
case LBM_TYPE_I: |
428 |
|
|
*s += (int32_t)sizeof(lbm_uint) + 1; |
429 |
|
|
break; |
430 |
|
|
case LBM_TYPE_U32: |
431 |
|
|
*s += 4 + 1; |
432 |
|
|
break; |
433 |
|
|
case LBM_TYPE_I32: |
434 |
|
|
*s += 4 + 1; |
435 |
|
|
break; |
436 |
|
|
case LBM_TYPE_U64: |
437 |
|
|
*s += 8 + 1; |
438 |
|
|
break; |
439 |
|
|
case LBM_TYPE_I64: |
440 |
|
|
*s += 8 + 1; |
441 |
|
|
break; |
442 |
|
|
case LBM_TYPE_FLOAT: |
443 |
|
|
*s += 4 + 1; |
444 |
|
|
break; |
445 |
|
|
case LBM_TYPE_DOUBLE: |
446 |
|
|
*s += 8 + 1; |
447 |
|
|
break; |
448 |
|
|
case LBM_TYPE_SYMBOL: |
449 |
|
|
*s += (int32_t)sizeof(lbm_uint) + 1; |
450 |
|
|
break; |
451 |
|
|
case LBM_TYPE_ARRAY: { |
452 |
|
|
lbm_int arr_size = lbm_heap_array_get_size(v); |
453 |
|
|
const uint8_t *d = lbm_heap_array_get_data_ro(v); |
454 |
|
|
if (arr_size > 0 && d != NULL) { |
455 |
|
|
*s += 1 + 4 + arr_size; |
456 |
|
|
} |
457 |
|
|
}break; |
458 |
|
|
} |
459 |
|
|
} |
460 |
|
|
|
461 |
|
|
static void flatten_node(lbm_value v, void *res) { |
462 |
|
|
bool *acc = (bool*)res; |
463 |
|
|
lbm_uint t = lbm_type_of(v); |
464 |
|
|
|
465 |
|
|
if (t >= LBM_POINTER_TYPE_FIRST && t < LBM_POINTER_TYPE_LAST) { |
466 |
|
|
t = t & ~(LBM_PTR_TO_CONSTANT_BIT); |
467 |
|
|
} |
468 |
|
|
|
469 |
|
|
if (lbm_is_ptr(v) && (v & LBM_PTR_TO_CONSTANT_BIT)) { |
470 |
|
|
*acc = *acc && fv_write_u8(S_CONSTANT_REF); |
471 |
|
|
#ifdef LBM64 |
472 |
|
|
*acc = *acc && fv_write_u64((lbm_uint)v); |
473 |
|
|
#else |
474 |
|
|
*acc = *acc && fv_write_u32((lbm_uint)v); |
475 |
|
|
#endif |
476 |
|
|
return; |
477 |
|
|
} |
478 |
|
|
|
479 |
|
|
switch (t) { |
480 |
|
|
case LBM_TYPE_CONS: |
481 |
|
|
*acc = *acc && i_f_cons(); |
482 |
|
|
break; |
483 |
|
|
case LBM_TYPE_LISPARRAY: { |
484 |
|
|
lbm_array_header_t *header = (lbm_array_header_t*)lbm_car(v); |
485 |
|
|
if (header) { |
486 |
|
|
uint32_t size = (uint32_t)(header->size / sizeof(lbm_value)); |
487 |
|
|
*acc = *acc && i_f_lisp_array(size); |
488 |
|
|
} else { |
489 |
|
|
// hmm |
490 |
|
|
} |
491 |
|
|
} break; |
492 |
|
|
case LBM_TYPE_BYTE: |
493 |
|
|
*acc = *acc && i_f_b((uint8_t)lbm_dec_as_char(v)); |
494 |
|
|
break; |
495 |
|
|
case LBM_TYPE_U: |
496 |
|
|
*acc = *acc && i_f_u(lbm_dec_u(v)); |
497 |
|
|
break; |
498 |
|
|
case LBM_TYPE_I: |
499 |
|
|
*acc = *acc && i_f_i(lbm_dec_i(v)); |
500 |
|
|
break; |
501 |
|
|
case LBM_TYPE_U32: |
502 |
|
|
*acc = *acc && i_f_u32(lbm_dec_as_u32(v)); |
503 |
|
|
break; |
504 |
|
|
case LBM_TYPE_I32: |
505 |
|
|
*acc = *acc && i_f_i32(lbm_dec_as_i32(v)); |
506 |
|
|
break; |
507 |
|
|
case LBM_TYPE_U64: |
508 |
|
|
*acc = *acc && i_f_u64(lbm_dec_as_u64(v)); |
509 |
|
|
break; |
510 |
|
|
case LBM_TYPE_I64: |
511 |
|
|
*acc = *acc && i_f_i64(lbm_dec_as_i64(v)); |
512 |
|
|
break; |
513 |
|
|
case LBM_TYPE_FLOAT: |
514 |
|
|
*acc = *acc && i_f_float(lbm_dec_as_float(v)); |
515 |
|
|
break; |
516 |
|
|
case LBM_TYPE_DOUBLE: |
517 |
|
|
*acc = *acc && i_f_double(lbm_dec_as_double(v)); |
518 |
|
|
break; |
519 |
|
|
case LBM_TYPE_SYMBOL: |
520 |
|
|
*acc = *acc && i_f_sym(v); |
521 |
|
|
break; |
522 |
|
|
case LBM_TYPE_ARRAY: { |
523 |
|
|
lbm_int s = lbm_heap_array_get_size(v); |
524 |
|
|
const uint8_t *d = lbm_heap_array_get_data_ro(v); |
525 |
|
|
if (s > 0 && d != NULL) { |
526 |
|
|
*acc = *acc && i_f_lbm_array((uint32_t)s, (uint8_t*)d); |
527 |
|
|
} |
528 |
|
|
}break; |
529 |
|
|
default: |
530 |
|
|
break; |
531 |
|
|
} |
532 |
|
|
} |
533 |
|
|
|
534 |
|
|
static int32_t image_flatten_size(lbm_value v) { |
535 |
|
|
int32_t s = 0; |
536 |
|
|
if (lbm_ptr_rev_trav(size_acc, v, &s)) |
537 |
|
|
return s; |
538 |
|
|
return -1; |
539 |
|
|
} |
540 |
|
|
|
541 |
|
|
static bool image_flatten_value(lbm_value v) { |
542 |
|
|
bool ok = true; |
543 |
|
|
bool trav_ok = lbm_ptr_rev_trav(flatten_node, v, &ok); |
544 |
|
|
return trav_ok && ok; // ok = enough space in image for flat val. |
545 |
|
|
// trav_ok = no cycles in input value. |
546 |
|
|
} |
547 |
|
|
|
548 |
|
|
// //////////////////////////////////////////////////////////// |
549 |
|
|
// |
550 |
|
|
|
551 |
|
|
char *lbm_image_get_version(void) { |
552 |
|
|
if (image_version) { |
553 |
|
|
return image_version; |
554 |
|
|
} else { |
555 |
|
|
int32_t pos = (int32_t)image_size-2; // fixed position version string. |
556 |
|
|
uint32_t val = read_u32(pos); pos --; |
557 |
|
|
if (val == VERSION_ENTRY) { |
558 |
|
|
int32_t size = (int32_t)read_u32(pos); |
559 |
|
|
image_version = (char*)(image_address + (pos - size)); |
560 |
|
|
return image_version; |
561 |
|
|
} |
562 |
|
|
} |
563 |
|
|
return NULL; |
564 |
|
|
} |
565 |
|
|
|
566 |
|
|
// //////////////////////////////////////////////////////////// |
567 |
|
|
// Constant heaps as part of an image. |
568 |
|
|
|
569 |
|
|
lbm_const_heap_t image_const_heap; |
570 |
|
|
lbm_uint image_const_heap_start_ix = 0; |
571 |
|
|
|
572 |
|
1786692 |
bool image_const_heap_write(lbm_uint w, lbm_uint ix) { |
573 |
|
|
#ifdef LBM64 |
574 |
|
|
int32_t i = (int32_t)(image_const_heap_start_ix + (ix * 2)); |
575 |
|
|
uint32_t *words = (uint32_t*)&w; |
576 |
|
|
bool r = image_write(words[0], i, false); |
577 |
|
|
r = r && image_write(words[1], i + 1, false); |
578 |
|
|
return r; |
579 |
|
|
#else |
580 |
|
1786692 |
int32_t i = (int32_t)(image_const_heap_start_ix + ix); |
581 |
|
1786692 |
return write_u32(w, &i, false); |
582 |
|
|
#endif |
583 |
|
|
} |
584 |
|
|
|
585 |
|
|
// //////////////////////////////////////////////////////////// |
586 |
|
|
// Image manipulation |
587 |
|
|
|
588 |
|
151050 |
lbm_uint *lbm_image_add_symbol(char *name, lbm_uint id, lbm_uint symlist) { |
589 |
|
|
// 64 bit | 32 bit |
590 |
|
|
// image[i] = SYMBOL_ENTRY | image[i] = SYMBOL_ENTRY |
591 |
|
|
// image[i-1] = symlist_ptr_high_word | image[i-1] = symlist_ptr |
592 |
|
|
// image[i-2] = symlist_ptr_low_word | image[i-2] = id |
593 |
|
|
// image[i-3] = id_high_word | image[i-3] = name_ptr |
594 |
|
|
// image[i-4] = id_low_word |
595 |
|
|
// image[i-5] = name_ptr_high_word |
596 |
|
|
// image[i-6] = name_ptr_low_word |
597 |
|
151050 |
bool r = write_u32(SYMBOL_ENTRY, &write_index,DOWNWARDS); |
598 |
✓✗✓✗
|
151050 |
r = r && write_lbm_uint(symlist, &write_index, DOWNWARDS); |
599 |
✓✗✓✗
|
151050 |
r = r && write_lbm_uint(id, &write_index, DOWNWARDS); |
600 |
✓✗✓✗
|
151050 |
r = r && write_lbm_uint((lbm_uint)name, &write_index, DOWNWARDS); |
601 |
|
151050 |
lbm_uint entry_ptr = (lbm_uint)(image_address + write_index + 1); |
602 |
✓✗ |
151050 |
if (r) |
603 |
|
151050 |
return (lbm_uint*)entry_ptr; |
604 |
|
|
return NULL; |
605 |
|
|
} |
606 |
|
|
|
607 |
|
|
// The symbol id is written to the link address upon image-boot |
608 |
|
438480 |
lbm_uint *lbm_image_add_and_link_symbol(char *name, lbm_uint id, lbm_uint symlist, lbm_uint *link) { |
609 |
|
|
// 64 bit | 32 bit |
610 |
|
|
// image[i] = SYMBOL_ENTRY | image[i] = SYMBOL_ENTRY |
611 |
|
|
// image[i-1] = link_ptr_high | image[i-1] link_ptr |
612 |
|
|
// image[i-2] = link_ptr_low | image[i-2] = symlist_ptr |
613 |
|
|
// image[i-3] = symlist_ptr_high_word | image[i-3] = id |
614 |
|
|
// image[i-4] = symlist_ptr_low_word | image[i-4] = name_ptr |
615 |
|
|
// image[i-5] = id_high_word |
616 |
|
|
// image[i-6] = id_low_word |
617 |
|
|
// image[i-7] = name_ptr_high_word |
618 |
|
|
// image[i-8] = name_ptr_low_word |
619 |
|
438480 |
bool r = write_u32(SYMBOL_LINK_ENTRY, &write_index,DOWNWARDS); |
620 |
✓✗✓✗
|
438480 |
r = r && write_lbm_uint((lbm_uint)link, &write_index, DOWNWARDS); |
621 |
✓✗✓✗
|
438480 |
r = r && write_lbm_uint(symlist, &write_index, DOWNWARDS); |
622 |
✓✗✓✗
|
438480 |
r = r && write_lbm_uint(id, &write_index, DOWNWARDS); |
623 |
✓✗✓✗
|
438480 |
r = r && write_lbm_uint((lbm_uint)name, &write_index, DOWNWARDS); |
624 |
|
438480 |
lbm_uint entry_ptr = (lbm_uint)(image_address + write_index + 1); |
625 |
✓✗ |
438480 |
if (r) |
626 |
|
438480 |
return (lbm_uint*)entry_ptr; |
627 |
|
|
return NULL; |
628 |
|
|
} |
629 |
|
|
|
630 |
|
|
bool lbm_image_save_global_env(void) { |
631 |
|
|
lbm_value *env = lbm_get_global_env(); |
632 |
|
|
if (env) { |
633 |
|
|
for (int i = 0; i < GLOBAL_ENV_ROOTS; i ++) { |
634 |
|
|
lbm_value curr = env[i]; |
635 |
|
|
while(lbm_is_cons(curr)) { |
636 |
|
|
lbm_value name_field = lbm_caar(curr); |
637 |
|
|
lbm_value val_field = lbm_cdr(lbm_car(curr)); |
638 |
|
|
|
639 |
|
|
if (lbm_is_constant(val_field)) { |
640 |
|
|
write_u32(BINDING_CONST, &write_index, DOWNWARDS); |
641 |
|
|
write_lbm_value(name_field, &write_index, DOWNWARDS); |
642 |
|
|
write_lbm_value(val_field, &write_index, DOWNWARDS); |
643 |
|
|
} else { |
644 |
|
|
|
645 |
|
|
int fv_size = image_flatten_size(val_field); |
646 |
|
|
if (fv_size > 0) { |
647 |
|
|
fv_size = (fv_size % 4 == 0) ? (fv_size / 4) : (fv_size / 4) + 1; // num 32bit words |
648 |
|
|
int tot_size = fv_size; //+ 1 + (int)(sizeof(lbm_uint) / 4); |
649 |
|
|
|
650 |
|
|
if (write_index + tot_size >= (int32_t)image_size) { |
651 |
|
|
return false; |
652 |
|
|
} |
653 |
|
|
write_u32(BINDING_FLAT, &write_index, DOWNWARDS); |
654 |
|
|
write_u32((uint32_t)fv_size , &write_index, DOWNWARDS); |
655 |
|
|
write_lbm_value(name_field, &write_index, DOWNWARDS); |
656 |
|
|
write_index = write_index - fv_size; // subtract fv_size |
657 |
|
|
if (image_flatten_value(val_field)) { // adds fv_size back |
658 |
|
|
// TODO: What error handling makes sense? |
659 |
|
|
fv_write_flush(); |
660 |
|
|
} |
661 |
|
|
write_index = write_index - fv_size - 1; // subtract fv_size |
662 |
|
|
} else { |
663 |
|
|
return false; |
664 |
|
|
} |
665 |
|
|
} |
666 |
|
|
curr = lbm_cdr(curr); |
667 |
|
|
} |
668 |
|
|
} |
669 |
|
|
return true; |
670 |
|
|
} |
671 |
|
|
return false; |
672 |
|
|
} |
673 |
|
|
|
674 |
|
|
// The extension table is created at system startup. |
675 |
|
|
// Extensions can also be added dynamically. |
676 |
|
|
// Dynamically added extensions have names starting with "ext-" |
677 |
|
|
// and their names are placed in RAM by the reader. |
678 |
|
|
// |
679 |
|
|
// Symbol_id -> index in extension table mapping |
680 |
|
|
// is created as extensions are added. |
681 |
|
|
// dynamic extensions are added after "built-in" extensions |
682 |
|
|
// and have higher indices. |
683 |
|
|
|
684 |
|
|
bool lbm_image_save_extensions(void) { |
685 |
|
|
bool r = true; |
686 |
|
|
lbm_uint num = lbm_get_num_extensions(); |
687 |
|
|
if (num > 0) { |
688 |
|
|
r = r && write_u32(EXTENSION_TABLE, &write_index, DOWNWARDS); |
689 |
|
|
r = r && write_u32((uint32_t)num , &write_index, DOWNWARDS); |
690 |
|
|
for (lbm_uint i = 0; i < num; i ++) { |
691 |
|
|
if (!r) return r; |
692 |
|
|
|
693 |
|
|
char *name_ptr = extension_table[i].name; |
694 |
|
|
lbm_uint addr; |
695 |
|
|
// when PIC, name pointers may move around |
696 |
|
|
// between restarts. It is also the case that |
697 |
|
|
// the FPTRs will move around as well. |
698 |
|
|
// This makes dynamic extensions useless on Linux. |
699 |
|
|
// Static extensions are fine as they will be re-added after image-boot |
700 |
|
|
// and faulty FPTRs will be replaced. |
701 |
|
|
//#ifdef __PIC__ |
702 |
|
|
//r = store_symbol_name_flash(name_ptr, &addr); |
703 |
|
|
//if (!r) return r; |
704 |
|
|
//name_ptr = (char *)addr; |
705 |
|
|
//#else |
706 |
|
|
if (lbm_memory_ptr_inside((lbm_uint *)name_ptr)) { |
707 |
|
|
r = store_symbol_name_flash(name_ptr, &addr); |
708 |
|
|
if (!r) return r; |
709 |
|
|
name_ptr = (char *)addr; |
710 |
|
|
} |
711 |
|
|
//#endif |
712 |
|
|
#ifdef LBM64 |
713 |
|
|
r = r && write_u64((uint64_t)name_ptr, &write_index, DOWNWARDS); |
714 |
|
|
r = r && write_u64((uint64_t)extension_table[i].fptr, &write_index, DOWNWARDS); |
715 |
|
|
#else |
716 |
|
|
r = r && write_u32((uint32_t)name_ptr, &write_index, DOWNWARDS); |
717 |
|
|
r = r && write_u32((uint32_t)extension_table[i].fptr, &write_index, DOWNWARDS); |
718 |
|
|
#endif |
719 |
|
|
} |
720 |
|
|
} |
721 |
|
|
return true; |
722 |
|
|
} |
723 |
|
|
|
724 |
|
|
static uint32_t last_const_heap_ix = 0; |
725 |
|
|
|
726 |
|
|
bool lbm_image_save_constant_heap_ix(void) { |
727 |
|
|
bool r = true; // saved or no need to save it. |
728 |
|
|
if (image_const_heap.next != last_const_heap_ix) { |
729 |
|
|
r = write_u32(CONSTANT_HEAP_IX, &write_index, DOWNWARDS); |
730 |
|
|
r = r && write_u32((uint32_t)image_const_heap.next, &write_index, DOWNWARDS); |
731 |
|
|
} |
732 |
|
|
return r; |
733 |
|
|
} |
734 |
|
|
|
735 |
|
|
bool lbm_image_exists(void) { |
736 |
|
|
uint32_t val = read_u32((int32_t)image_size - 1); |
737 |
|
|
return val == IMAGE_INITIALIZED; |
738 |
|
|
} |
739 |
|
|
|
740 |
|
21924 |
void lbm_image_init(uint32_t* image_mem_address, |
741 |
|
|
uint32_t image_size_words, |
742 |
|
|
lbm_image_write_fun image_write_fun) { |
743 |
|
21924 |
image_write = image_write_fun; |
744 |
|
21924 |
image_address = image_mem_address; |
745 |
|
21924 |
image_size = image_size_words; |
746 |
|
21924 |
write_index = (int32_t)image_size_words -1; |
747 |
|
21924 |
image_has_extensions = false; |
748 |
|
21924 |
image_version = NULL; |
749 |
|
21924 |
} |
750 |
|
|
|
751 |
|
21924 |
void lbm_image_create(char *version_str) { |
752 |
|
21924 |
write_u32(IMAGE_INITIALIZED, &write_index, DOWNWARDS); |
753 |
✓✗ |
21924 |
if (version_str) { |
754 |
|
21924 |
uint32_t bytes = strlen(version_str) + 1; |
755 |
✗✓ |
21924 |
uint32_t words = (bytes % 4 == 0) ? bytes / 4 : (bytes / 4) + 1; |
756 |
|
21924 |
write_u32(VERSION_ENTRY, &write_index, DOWNWARDS); |
757 |
|
21924 |
write_u32(words, &write_index, DOWNWARDS); |
758 |
|
21924 |
uint32_t w = 0; |
759 |
|
21924 |
char *buf = (char*)&w; |
760 |
|
21924 |
uint32_t i = 0; |
761 |
|
21924 |
int32_t ix = write_index - (int32_t)(words -1); |
762 |
|
21924 |
int wi = 0; |
763 |
✓✓ |
263088 |
while (i < bytes) { |
764 |
✓✓ |
241164 |
if (wi == 0 ) { |
765 |
|
21924 |
w = 0; |
766 |
|
|
} |
767 |
✓✓ |
241164 |
if (wi == 4) wi = 0; |
768 |
|
241164 |
buf[wi] = version_str[i]; |
769 |
✓✓ |
241164 |
if (wi == 3) { |
770 |
|
43848 |
write_u32(w, &ix, UPWARDS); |
771 |
|
|
} |
772 |
|
241164 |
i ++; |
773 |
|
241164 |
wi ++; |
774 |
|
|
} |
775 |
✓✗ |
21924 |
if (wi != 0) { |
776 |
|
21924 |
write_u32(w, &ix, UPWARDS); |
777 |
|
|
} |
778 |
|
21924 |
write_index -= (int32_t)words; |
779 |
|
|
} |
780 |
|
21924 |
} |
781 |
|
|
|
782 |
|
|
|
783 |
|
21924 |
bool lbm_image_boot(void) { |
784 |
|
|
//process image |
785 |
|
21924 |
int32_t pos = (int32_t)image_size-1; |
786 |
|
21924 |
last_const_heap_ix = 0; |
787 |
|
|
|
788 |
✗✓✓✗
|
65772 |
while (pos >= 0 && pos > (int32_t)last_const_heap_ix) { |
789 |
|
65772 |
uint32_t val = read_u32(pos); |
790 |
|
65772 |
pos --; |
791 |
✓✓✗✗ ✗✗✗✗ ✓ |
65772 |
switch(val) { |
792 |
|
21924 |
case IMAGE_INITIALIZED: { |
793 |
|
21924 |
image_const_heap_start_ix = 0; // const heap starts at 0 |
794 |
|
21924 |
lbm_const_heap_init(image_const_heap_write, |
795 |
|
|
&image_const_heap, |
796 |
|
|
(lbm_uint*)(image_address)); |
797 |
|
|
// initialized is a one word field |
798 |
|
21924 |
} break; |
799 |
|
21924 |
case VERSION_ENTRY: { |
800 |
|
21924 |
uint32_t size = read_u32(pos); pos --; |
801 |
|
21924 |
image_version = (char*)(image_address + (pos - (int32_t)size + 1)); |
802 |
|
21924 |
pos -= (int32_t)size; |
803 |
|
21924 |
} break; |
804 |
|
|
case CONSTANT_HEAP_IX: { |
805 |
|
|
uint32_t next = read_u32(pos); |
806 |
|
|
pos --; |
807 |
|
|
last_const_heap_ix = next; |
808 |
|
|
image_const_heap.next = next; |
809 |
|
|
} break; |
810 |
|
|
case BINDING_CONST: { |
811 |
|
|
// on 64 bit | on 32 bit |
812 |
|
|
// pos -> key_high | pos -> key |
813 |
|
|
// pos - 1 -> key_low | pos - 1 -> val |
814 |
|
|
// pos - 2 -> val_high |
815 |
|
|
// pos - 3 -> val_low |
816 |
|
|
#ifdef LBM64 |
817 |
|
|
lbm_uint bind_key = read_u64(pos-1); |
818 |
|
|
lbm_uint bind_val = read_u64(pos-3); |
819 |
|
|
pos -= 4; |
820 |
|
|
#else |
821 |
|
|
lbm_uint bind_key = read_u32(pos); |
822 |
|
|
lbm_uint bind_val = read_u32(pos-1); |
823 |
|
|
pos -= 2; |
824 |
|
|
#endif |
825 |
|
|
lbm_uint ix_key = lbm_dec_sym(bind_key) & GLOBAL_ENV_MASK; |
826 |
|
|
lbm_value *global_env = lbm_get_global_env(); |
827 |
|
|
lbm_uint orig_env = global_env[ix_key]; |
828 |
|
|
lbm_value new_env = lbm_env_set(orig_env,bind_key,bind_val); |
829 |
|
|
|
830 |
|
|
if (lbm_is_symbol(new_env)) { |
831 |
|
|
return false; |
832 |
|
|
} |
833 |
|
|
global_env[ix_key] = new_env; |
834 |
|
|
} break; |
835 |
|
|
case BINDING_FLAT: { |
836 |
|
|
// on 64 bit | on 32 bit |
837 |
|
|
// pos -> size | pos -> size |
838 |
|
|
// pos - 1 -> key_high | pos - 1 -> key |
839 |
|
|
// pos - 2 -> key_low |
840 |
|
|
// |
841 |
|
|
int32_t s = (int32_t)read_u32(pos); |
842 |
|
|
// size in 32 or 64 bit words. |
843 |
|
|
#ifdef LBM64 |
844 |
|
|
lbm_uint bind_key = read_u64(pos-2); |
845 |
|
|
pos -= 3; |
846 |
|
|
#else |
847 |
|
|
lbm_uint bind_key = read_u32(pos-1); |
848 |
|
|
pos -= 2; |
849 |
|
|
#endif |
850 |
|
|
|
851 |
|
|
pos -= s; |
852 |
|
|
lbm_flat_value_t fv; |
853 |
|
|
fv.buf = (uint8_t*)(image_address + pos); |
854 |
|
|
fv.buf_size = (uint32_t)s * sizeof(lbm_uint); // GEQ to actual buf |
855 |
|
|
fv.buf_pos = 0; |
856 |
|
|
lbm_value unflattened; |
857 |
|
|
lbm_unflatten_value(&fv, &unflattened); |
858 |
|
|
if (lbm_is_symbol_merror(unflattened)) { |
859 |
|
|
lbm_perform_gc(); |
860 |
|
|
lbm_unflatten_value(&fv, &unflattened); |
861 |
|
|
} |
862 |
|
|
|
863 |
|
|
lbm_uint ix_key = lbm_dec_sym(bind_key) & GLOBAL_ENV_MASK; |
864 |
|
|
lbm_value *global_env = lbm_get_global_env(); |
865 |
|
|
lbm_uint orig_env = global_env[ix_key]; |
866 |
|
|
lbm_value new_env = lbm_env_set(orig_env,bind_key,unflattened); |
867 |
|
|
|
868 |
|
|
if (lbm_is_symbol(new_env)) { |
869 |
|
|
return false; |
870 |
|
|
} |
871 |
|
|
global_env[ix_key] = new_env; |
872 |
|
|
pos --; |
873 |
|
|
} break; |
874 |
|
|
case SYMBOL_ENTRY: { |
875 |
|
|
// on 64 bit | on 32 bit |
876 |
|
|
// pos -> symlist_addr_high_word | pos -> symlist_ptr |
877 |
|
|
// pos - 1 -> symlist_addr_low_word | pos - 1 -> id |
878 |
|
|
// pos - 2 -> id_high_word | pos - 2 -> name_ptr |
879 |
|
|
// pos - 3 -> id_low_word | |
880 |
|
|
// pos - 4 -> name_ptr_high_word | |
881 |
|
|
// pos - 5 -> name_ptr_low_word | |
882 |
|
|
#ifdef LBM64 |
883 |
|
|
int32_t entry_pos = pos - 5; |
884 |
|
|
lbm_symrepr_set_symlist((lbm_uint*)(image_address + entry_pos)); |
885 |
|
|
pos -= 6; |
886 |
|
|
#else |
887 |
|
|
int32_t entry_pos = pos - 2; |
888 |
|
|
lbm_symrepr_set_symlist((lbm_uint*)(image_address + entry_pos)); |
889 |
|
|
pos -= 3; |
890 |
|
|
#endif |
891 |
|
|
} break; |
892 |
|
|
case SYMBOL_LINK_ENTRY: { |
893 |
|
|
// on 64 bits | on 32 bit |
894 |
|
|
// pos -> link_ptr_high | pos -> link_ptr |
895 |
|
|
// pos - 1 -> link_ptr_low | pos - 1 -> symlist_ptr |
896 |
|
|
// pos - 2 -> symlist_addr_high_word | pos - 2 -> id |
897 |
|
|
// pos - 3 -> symlist_addr_low_word | pos - 3 -> name_ptr; |
898 |
|
|
// pos - 4 -> id_high_word |
899 |
|
|
// pos - 5 -> id_low_word |
900 |
|
|
// pos - 6 -> name_ptr_high_word |
901 |
|
|
// pos - 7 -> name_ptr_low_word |
902 |
|
|
//int32_t entry_pos = pos - (int32_t)(3 * (sizeof(lbm_uint) / 4)); |
903 |
|
|
lbm_uint link_ptr; |
904 |
|
|
lbm_uint sym_id; |
905 |
|
|
#ifdef LBM64 |
906 |
|
|
link_ptr = read_u64(pos-1); |
907 |
|
|
sym_id = read_u64(pos-5); |
908 |
|
|
*((lbm_uint*)link_ptr) = sym_id; |
909 |
|
|
lbm_symrepr_set_symlist((lbm_uint*)(image_address + (pos - 7))); |
910 |
|
|
pos -= 8; |
911 |
|
|
#else |
912 |
|
|
link_ptr = read_u32(pos); |
913 |
|
|
sym_id = read_u32(pos-2); |
914 |
|
|
*((lbm_uint*)link_ptr) = sym_id; |
915 |
|
|
lbm_symrepr_set_symlist((lbm_uint*)(image_address + (pos - 3))); |
916 |
|
|
pos -= 4; |
917 |
|
|
#endif |
918 |
|
|
} break; |
919 |
|
|
case EXTENSION_TABLE: { |
920 |
|
|
// on 64 bit | on 32 bit |
921 |
|
|
// pos -> name_ptr_high | pos -> name_ptr |
922 |
|
|
// pos - 1 -> name_ptr_low | pos - 1 -> fptr |
923 |
|
|
// pos - 2 -> fptr_high |
924 |
|
|
// pos - 3 -> fptr_low |
925 |
|
|
int32_t num = (int32_t)read_u32(pos); pos --; |
926 |
|
|
|
927 |
|
|
int32_t i = 0; |
928 |
|
|
for (i = 0; i < num; i ++) { |
929 |
|
|
lbm_uint name; |
930 |
|
|
lbm_uint fptr; |
931 |
|
|
#ifdef LBM64 |
932 |
|
|
name = read_u64(pos-1); |
933 |
|
|
fptr = read_u64(pos-3); |
934 |
|
|
pos -= 4; |
935 |
|
|
#else |
936 |
|
|
name = read_u32(pos); |
937 |
|
|
fptr = read_u32(pos-1); |
938 |
|
|
pos -= 2; |
939 |
|
|
#endif |
940 |
|
|
extension_table[i].name = (char*)name; |
941 |
|
|
extension_table[i].fptr = (extension_fptr)fptr; |
942 |
|
|
} |
943 |
|
|
lbm_extensions_set_next((lbm_uint)i); |
944 |
|
|
image_has_extensions = true; |
945 |
|
|
} break; |
946 |
|
21924 |
default: |
947 |
|
21924 |
write_index = pos+1; |
948 |
|
21924 |
goto done_loading_image; |
949 |
|
|
break; |
950 |
|
|
} |
951 |
|
|
} |
952 |
|
|
done_loading_image: |
953 |
|
21924 |
return true; |
954 |
|
|
} |