1 /*
2 $Id: addressobj.c 2596 2021-04-18 18:52:11Z soci $
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 2 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 along
15 with this program; if not, write to the Free Software Foundation, Inc.,
16 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17
18 */
19 #include "addressobj.h"
20 #include <string.h>
21 #include "error.h"
22 #include "eval.h"
23 #include "variables.h"
24 #include "arguments.h"
25 #include "instruction.h"
26
27 #include "boolobj.h"
28 #include "strobj.h"
29 #include "intobj.h"
30 #include "typeobj.h"
31 #include "noneobj.h"
32 #include "errorobj.h"
33 #include "floatobj.h"
34 #include "bitsobj.h"
35 #include "bytesobj.h"
36 #include "registerobj.h"
37
38 static Type obj;
39
40 Type *const ADDRESS_OBJ = &obj;
41
address_from_obj(Obj * v1,linepos_t epoint)42 static MUST_CHECK Obj *address_from_obj(Obj *v1, linepos_t epoint) {
43 switch (v1->obj->type) {
44 case T_BOOL:
45 case T_INT:
46 case T_BITS:
47 case T_FLOAT:
48 case T_BYTES:
49 case T_STR:
50 return new_address(val_reference(v1), A_NONE);
51 case T_NONE:
52 case T_ERROR:
53 case T_ADDRESS: return val_reference(v1);
54 default: break;
55 }
56 return new_error_conv(v1, ADDRESS_OBJ, epoint);
57 }
58
convert(oper_t op)59 static MUST_CHECK Obj *convert(oper_t op) {
60 return address_from_obj(op->v2, op->epoint2);
61 }
62
destroy(Obj * o1)63 static FAST_CALL void destroy(Obj *o1) {
64 Address *v1 = Address(o1);
65 val_destroy(v1->val);
66 }
67
garbage(Obj * o1,int i)68 static FAST_CALL void garbage(Obj *o1, int i) {
69 Address *v1 = Address(o1);
70 Obj *v;
71 switch (i) {
72 case -1:
73 v1->val->refcount--;
74 return;
75 case 0:
76 return;
77 case 1:
78 v = v1->val;
79 if ((v->refcount & SIZE_MSB) != 0) {
80 v->refcount -= SIZE_MSB - 1;
81 v->obj->garbage(v, 1);
82 } else v->refcount++;
83 return;
84 }
85 }
86
same(const Obj * o1,const Obj * o2)87 static FAST_CALL bool same(const Obj *o1, const Obj *o2) {
88 const Address *v1 = Address(o1), *v2 = Address(o2);
89 return o1->obj == o2->obj && v1->type == v2->type && v1->val->obj->same(v1->val, v2->val);
90 }
91
truth(Obj * o1,Truth_types type,linepos_t epoint)92 static MUST_CHECK Obj *truth(Obj *o1, Truth_types type, linepos_t epoint) {
93 Address *v1 = Address(o1);
94 Obj *v;
95 if (v1->type != A_NONE && v1->val != none_value && v1->val->obj != ERROR_OBJ) {
96 return DEFAULT_OBJ->truth(o1, type, epoint);
97 }
98 v = v1->val;
99 return v->obj->truth(v, type, epoint);
100 }
101
hash(Obj * o1,int * hs,linepos_t epoint)102 static MUST_CHECK Obj *hash(Obj *o1, int *hs, linepos_t epoint) {
103 Address *v1 = Address(o1);
104 Obj *v = v1->val;
105 Obj *err = v->obj->hash(v, hs, epoint);
106 if (err == NULL) {
107 *hs = ((unsigned int)*hs + v1->type) & ((~0U) >> 1);
108 }
109 return err;
110 }
111
repr(Obj * o1,linepos_t epoint,size_t maxsize)112 static MUST_CHECK Obj *repr(Obj *o1, linepos_t epoint, size_t maxsize) {
113 Address *v1 = Address(o1);
114 uint8_t *s;
115 size_t len, chars;
116 char buffer[100], buffer2[100], *b2;
117 atype_t addrtype;
118 unsigned int ind, ind2;
119 Obj *tmp;
120 Str *v, *str;
121
122 ind2 = 0;
123 addrtype = v1->type;
124 ind = 99;
125 buffer2[ind] = '\0';
126 if (addrtype == A_NONE) {
127 ind -= 8;
128 memcpy(&buffer2[ind], "address(", 8);
129 buffer[ind2++] = ')';
130 } else {
131 while ((addrtype & MAX_ADDRESS_MASK) != 0) {
132 uint32_t mode;
133 switch ((Address_types)((addrtype & 0xf000) >> 12)) {
134 case A_XR: mode = (',' << 16) + ('x' << 24);break;
135 case A_YR: mode = (',' << 16) + ('y' << 24);break;
136 case A_ZR: mode = (',' << 16) + ('z' << 24);break;
137 case A_SR: mode = (',' << 16) + ('s' << 24);break;
138 case A_RR: mode = (',' << 16) + ('r' << 24);break;
139 case A_DR: mode = (',' << 16) + ('d' << 24);break;
140 case A_BR: mode = (',' << 16) + ('b' << 24);break;
141 case A_KR: mode = (',' << 16) + ('k' << 24);break;
142 case A_I: mode = ('(' << 8) + (')' << 16);break;
143 case A_LI: mode = ('[' << 8) + (']' << 16);break;
144 case A_IMMEDIATE_SIGNED: mode = ('#' << 8) + '+';break;
145 case A_IMMEDIATE: mode = '#' << 8;break;
146 default: mode = 0;
147 }
148 if ((char)mode != '\0') buffer2[--ind] = (char)mode;
149 mode >>= 8;
150 if ((char)mode != '\0') buffer2[--ind] = (char)mode;
151 mode >>= 8;
152 if ((char)mode != '\0') buffer[ind2++] = (char)mode;
153 mode >>= 8;
154 if ((char)mode != '\0') buffer[ind2++] = (char)mode;
155 addrtype <<= 4;
156 }
157 }
158 b2 = buffer2 + ind;
159 ind = 99 - ind;
160
161 chars = ind + ind2;
162 if (chars > maxsize) return NULL;
163 tmp = v1->val->obj->repr(v1->val, epoint, maxsize - chars);
164 if (tmp == NULL || tmp->obj != STR_OBJ) return tmp;
165 str = Str(tmp);
166 len = chars + str->len;
167 if (len < chars) goto error; /* overflow */
168 chars += str->chars;
169 if (chars > maxsize) {
170 error:
171 val_destroy(tmp);
172 return NULL;
173 }
174
175 v = new_str2(len);
176 if (v == NULL) goto error;
177 v->chars = chars;
178 s = v->data;
179 if (ind != 0) {
180 memcpy(s, b2, ind);
181 s += ind;
182 }
183 if (str->len != 0) {
184 memcpy(s, str->data, str->len);
185 s += str->len;
186 }
187 if (ind2 != 0) memcpy(s, buffer, ind2);
188 val_destroy(tmp);
189 return Obj(v);
190 }
191
str(Obj * o1,linepos_t epoint,size_t maxsize)192 static MUST_CHECK Obj *str(Obj *o1, linepos_t epoint, size_t maxsize) {
193 Address *v1 = Address(o1);
194 if (v1->type == A_NONE) {
195 o1 = v1->val;
196 return o1->obj->repr(o1, epoint, maxsize);
197 }
198 return repr(o1, epoint, maxsize);
199 }
200
check_addr(atype_t type)201 bool check_addr(atype_t type) {
202 while (type != A_NONE) {
203 switch ((Address_types)(type & 0xf)) {
204 case A_I:
205 case A_LI: return true;
206 case A_IMMEDIATE:
207 case A_IMMEDIATE_SIGNED:
208 case A_KR:
209 case A_DR:
210 case A_BR:
211 case A_XR:
212 case A_YR:
213 case A_ZR:
214 case A_RR:
215 case A_SR:
216 case A_NONE: break;
217 }
218 type >>= 4;
219 }
220 return false;
221 }
222
check_addr2(atype_t type)223 static inline bool check_addr2(atype_t type) {
224 while (type != A_NONE) {
225 switch ((Address_types)(type & 0xf)) {
226 case A_KR:
227 case A_DR:
228 case A_BR:
229 case A_XR:
230 case A_YR:
231 case A_ZR:
232 case A_RR:
233 case A_SR:
234 case A_I:
235 case A_LI: return true;
236 case A_IMMEDIATE:
237 case A_IMMEDIATE_SIGNED:
238 case A_NONE: break;
239 }
240 type >>= 4;
241 }
242 return false;
243 }
244
register_to_indexing(unsigned int c)245 Address_types register_to_indexing(unsigned int c) {
246 switch (c) {
247 case 's': return A_SR;
248 case 'r': return A_RR;
249 case 'z': return A_ZR;
250 case 'y': return A_YR;
251 case 'x': return A_XR;
252 case 'd': return A_DR;
253 case 'b': return A_BR;
254 case 'k': return A_KR;
255 default: return A_NONE;
256 }
257 }
258
address(const Obj * o1)259 static FAST_CALL uint32_t address(const Obj *o1) {
260 const Address *v1 = Address(o1);
261 Obj *v = v1->val;
262 uint32_t am = v->obj->address(v);
263 atype_t type = v1->type;
264 while (type != A_NONE) {
265 am <<= 4;
266 type >>= 4;
267 }
268 return am | v1->type;
269 }
270
ival(Obj * o1,ival_t * iv,unsigned int bits,linepos_t epoint)271 static MUST_CHECK Error *ival(Obj *o1, ival_t *iv, unsigned int bits, linepos_t epoint) {
272 Address *v1 = Address(o1);
273 Obj *v;
274 if (v1->type != A_NONE && v1->val != none_value && v1->val->obj != ERROR_OBJ) {
275 return DEFAULT_OBJ->ival(o1, iv, bits, epoint);
276 }
277 v = v1->val;
278 return v->obj->ival(v, iv, bits, epoint);
279 }
280
uval(Obj * o1,uval_t * uv,unsigned int bits,linepos_t epoint)281 static MUST_CHECK Error *uval(Obj *o1, uval_t *uv, unsigned int bits, linepos_t epoint) {
282 Address *v1 = Address(o1);
283 Obj *v;
284 if (v1->type != A_NONE && v1->val != none_value && v1->val->obj != ERROR_OBJ) {
285 return DEFAULT_OBJ->uval(o1, uv, bits, epoint);
286 }
287 v = v1->val;
288 return v->obj->uval(v, uv, bits, epoint);
289 }
290
uval2(Obj * o1,uval_t * uv,unsigned int bits,linepos_t epoint)291 static MUST_CHECK Error *uval2(Obj *o1, uval_t *uv, unsigned int bits, linepos_t epoint) {
292 Address *v1 = Address(o1);
293 Obj *v;
294 if (v1->type != A_NONE && v1->val != none_value && v1->val->obj != ERROR_OBJ) {
295 return DEFAULT_OBJ->uval2(o1, uv, bits, epoint);
296 }
297 v = v1->val;
298 return v->obj->uval2(v, uv, bits, epoint);
299 }
300
iaddress(Obj * o1,ival_t * iv,unsigned int bits,linepos_t epoint)301 static MUST_CHECK Error *iaddress(Obj *o1, ival_t *iv, unsigned int bits, linepos_t epoint) {
302 Address *v1 = Address(o1);
303 Obj *v = v1->val;
304 return v->obj->iaddress(v, iv, bits, epoint);
305 }
306
uaddress(Obj * o1,uval_t * uv,unsigned int bits,linepos_t epoint)307 static MUST_CHECK Error *uaddress(Obj *o1, uval_t *uv, unsigned int bits, linepos_t epoint) {
308 Address *v1 = Address(o1);
309 Obj *v = v1->val;
310 return v->obj->uaddress(v, uv, bits, epoint);
311 }
312
float_from_address(Address * v1,linepos_t epoint)313 MUST_CHECK Obj *float_from_address(Address *v1, linepos_t epoint) {
314 if (v1->type != A_NONE && v1->val != none_value && v1->val->obj != ERROR_OBJ) {
315 return new_error_conv(Obj(v1), FLOAT_OBJ, epoint);
316 }
317 return float_from_obj(v1->val, epoint);
318 }
319
int_from_address(Address * v1,linepos_t epoint)320 MUST_CHECK Obj *int_from_address(Address *v1, linepos_t epoint) {
321 if (v1->type != A_NONE && v1->val != none_value && v1->val->obj != ERROR_OBJ) {
322 return new_error_conv(Obj(v1), INT_OBJ, epoint);
323 }
324 return int_from_obj(v1->val, epoint);
325 }
326
bits_from_address(Address * v1,linepos_t epoint)327 MUST_CHECK Obj *bits_from_address(Address *v1, linepos_t epoint) {
328 if (v1->type != A_NONE && v1->val != none_value && v1->val->obj != ERROR_OBJ) {
329 return new_error_conv(Obj(v1), BITS_OBJ, epoint);
330 }
331 return bits_from_obj(v1->val, epoint);
332 }
333
bytes_from_address(Address * v1,linepos_t epoint)334 MUST_CHECK Obj *bytes_from_address(Address *v1, linepos_t epoint) {
335 if (v1->type != A_NONE && v1->val != none_value && v1->val->obj != ERROR_OBJ) {
336 return new_error_conv(Obj(v1), BYTES_OBJ, epoint);
337 }
338 return bytes_from_obj(v1->val, epoint);
339 }
340
sign(Obj * o1,linepos_t epoint)341 static MUST_CHECK Obj *sign(Obj *o1, linepos_t epoint) {
342 Address *v1 = Address(o1);
343 Obj *v;
344 if (v1->type != A_NONE && v1->val != none_value && v1->val->obj != ERROR_OBJ) {
345 return DEFAULT_OBJ->sign(o1, epoint);
346 }
347 v = v1->val;
348 return v->obj->sign(v, epoint);
349 }
350
function(oper_t op)351 static MUST_CHECK Obj *function(oper_t op) {
352 Address *v1 = Address(op->v2);
353 Obj *v;
354 if (v1->type != A_NONE && v1->val != none_value && v1->val->obj != ERROR_OBJ) {
355 return DEFAULT_OBJ->function(op);
356 }
357 op->v2 = v = v1->val;
358 op->inplace = op->inplace == Obj(v1) && v->refcount == 1 ? v : NULL;
359 return v->obj->function(op);
360 }
361
calc1(oper_t op)362 static MUST_CHECK Obj *calc1(oper_t op) {
363 Obj *result;
364 Address *v1 = Address(op->v1);
365 atype_t am = v1->type;
366 switch (op->op) {
367 case O_LNOT:
368 case O_STRING:
369 if (am != A_NONE) break;
370 /* fall through */
371 case O_BANK:
372 case O_HIGHER:
373 case O_LOWER:
374 case O_HWORD:
375 case O_WORD:
376 case O_BSWORD:
377 case O_INV:
378 case O_NEG:
379 case O_POS:
380 if (check_addr2(am)) break;
381 op->v1 = v1->val;
382 op->inplace = NULL;
383 result = op->v1->obj->calc1(op);
384 if (am == A_NONE) return result;
385 return new_address(result, am);
386 default: break;
387 }
388 if (v1->val == none_value || v1->val->obj == ERROR_OBJ) return val_reference(v1->val);
389 return obj_oper_error(op);
390 }
391
slice(oper_t op,argcount_t indx)392 static MUST_CHECK Obj *slice(oper_t op, argcount_t indx) {
393 Obj *val = Address(op->v1)->val;
394 if (val == none_value || val->obj == ERROR_OBJ) {
395 return val_reference(val);
396 }
397 return DEFAULT_OBJ->slice(op, indx);
398 }
399
calc2(oper_t op)400 static MUST_CHECK Obj *calc2(oper_t op) {
401 Obj *o2 = op->v2, *result;
402 Address *v1 = Address(op->v1);
403 atype_t am;
404 if (op->op == O_LAND || op->op == O_LOR) {
405 bool i;
406 result = truth(Obj(v1), TRUTH_BOOL, op->epoint);
407 if (result->obj != BOOL_OBJ) return result;
408 i = (result == true_value) != (op->op == O_LOR);
409 val_destroy(result);
410 if (diagnostics.strict_bool) err_msg_bool_oper(op);
411 return val_reference(i ? o2 : Obj(v1));
412 }
413 switch (o2->obj->type) {
414 case T_ADDRESS:
415 {
416 Address *v2 = Address(o2);
417 atype_t am2 = v2->type;
418 am = v1->type;
419 switch (op->op) {
420 case O_CMP:
421 case O_EQ:
422 case O_NE:
423 case O_MIN:
424 case O_LT:
425 case O_LE:
426 case O_MAX:
427 case O_GT:
428 case O_GE:
429 if (am == am2) {
430 op->v1 = v1->val;
431 op->v2 = v2->val;
432 op->inplace = NULL;
433 return op->v1->obj->calc2(op);
434 }
435 return obj_oper_compare(op, (am < am2) ? -1 : 1);
436 case O_ADD:
437 if (check_addr(am)) break;
438 if (check_addr(am2)) break;
439 op->v1 = v1->val;
440 op->v2 = v2->val;
441 op->inplace = NULL;
442 result = op->v1->obj->calc2(op);
443 if (am == A_NONE && v2->type == A_NONE) return result;
444 while ((Address_types)(am2 & 0xf) != A_NONE) { am <<= 4; am2 >>= 4; }
445 return new_address(result, am | v2->type);
446 case O_SUB:
447 if (check_addr(am)) break;
448 if (check_addr(am2)) break;
449 {
450 atype_t am1 = A_NONE;
451 for (; (am & MAX_ADDRESS_MASK) != 0; am <<= 4) {
452 atype_t amc = (am >> 12) & 0xf;
453 atype_t am3, am4;
454 if (amc == A_NONE) continue;
455 am3 = A_NONE; am4 = am2;
456 while (am4 != A_NONE) {
457 atype_t am5 = (am4 & 0xf);
458 if (amc == am5) amc = A_NONE;
459 else am3 = (am3 << 4) | am5;
460 am4 >>= 4;
461 }
462 am2 = am3;
463 if (amc == A_NONE) continue;
464 am1 = (am1 << 4) | amc;
465 }
466 if (am2 != A_NONE) break;
467 op->v1 = v1->val;
468 op->v2 = v2->val;
469 op->inplace = NULL;
470 result = op->v1->obj->calc2(op);
471 if (am1 == A_NONE) return result;
472 return new_address(result, am1);
473 }
474 case O_XOR:
475 if (check_addr(am)) break;
476 if (check_addr(am2)) break;
477 if (am == am2) {
478 op->v1 = v1->val;
479 op->v2 = v2->val;
480 op->inplace = NULL;
481 return op->v1->obj->calc2(op);
482 }
483 break;
484 default:
485 break;
486 }
487 break;
488 }
489 case T_BOOL:
490 case T_INT:
491 case T_BITS:
492 case T_FLOAT:
493 case T_BYTES:
494 case T_STR:
495 am = v1->type;
496 switch (op->op) {
497 case O_CMP:
498 case O_EQ:
499 case O_NE:
500 case O_MIN:
501 case O_LT:
502 case O_LE:
503 case O_MAX:
504 case O_GT:
505 case O_GE:
506 if (am == A_NONE || (am == A_DR && dpage == 0) || (am == A_BR && databank == 0)) {
507 op->v1 = v1->val;
508 op->inplace = NULL;
509 return op->v1->obj->calc2(op);
510 }
511 break;
512 default:
513 if (am == A_NONE) {
514 op->v1 = v1->val;
515 op->inplace = NULL;
516 return op->v1->obj->calc2(op);
517 }
518 if (check_addr2(am)) break;
519 goto ok;
520 case O_ADD:
521 case O_SUB:
522 if (check_addr(am)) break;
523 ok:
524 op->v1 = v1->val;
525 op->inplace = NULL;
526 return new_address(op->v1->obj->calc2(op), am);
527 }
528 break;
529 case T_REGISTER:
530 if (Register(op->v2)->len == 1) {
531 Address_types am2 = register_to_indexing(Register(op->v2)->data[0]);
532 if (am2 == A_NONE) break;
533 if (op->op == O_ADD) {
534 return new_address(val_reference(v1->val), v1->type << 4 | am2);
535 }
536 if (op->op == O_SUB) {
537 atype_t am1 = A_NONE;
538 for (am = v1->type; ; am >>= 4) {
539 atype_t amc = am & 0xf;
540 switch (amc) {
541 case A_I:
542 case A_LI:
543 case A_IMMEDIATE:
544 case A_IMMEDIATE_SIGNED:
545 if (am2 == A_NONE) {
546 am1 = (am1 >> 4) | (amc << 12);
547 continue;
548 }
549 break;
550 case A_KR:
551 case A_DR:
552 case A_BR:
553 case A_XR:
554 case A_YR:
555 case A_ZR:
556 case A_RR:
557 case A_SR:
558 if (amc == am2) {
559 am2 = A_NONE;
560 continue;
561 }
562 am1 = (am1 >> 4) | (amc << 12);
563 continue;
564 default: break;
565 }
566 break;
567 }
568 if (am2 != A_NONE) break;
569 if (am1 != A_NONE) while ((am1 & 0xf) == A_NONE) am1 >>= 4;
570 return new_address(val_reference(v1->val), am1);
571 }
572 }
573 break;
574 default:
575 if (op->op != O_MEMBER && op->op != O_X) {
576 return o2->obj->rcalc2(op);
577 }
578 if (o2 == none_value || o2->obj == ERROR_OBJ) return val_reference(o2);
579 }
580 if (v1->val == none_value || v1->val->obj == ERROR_OBJ) return val_reference(v1->val);
581 return obj_oper_error(op);
582 }
583
rcalc2(oper_t op)584 static MUST_CHECK Obj *rcalc2(oper_t op) {
585 const Type *t1 = op->v1->obj;
586 Address *v2 = Address(op->v2);
587 atype_t am;
588 switch (t1->type) {
589 case T_BOOL:
590 case T_INT:
591 case T_BITS:
592 case T_FLOAT:
593 case T_BYTES:
594 case T_GAP:
595 am = v2->type;
596 switch (op->op) {
597 default:
598 if (am == A_NONE) {
599 op->v2 = v2->val;
600 op->inplace = NULL;
601 return t1->calc2(op);
602 }
603 break;
604 case O_MUL:
605 case O_OR:
606 case O_XOR:
607 case O_AND:
608 if (check_addr2(am)) break;
609 goto ok;
610 case O_ADD:
611 if (check_addr(am)) break;
612 ok:
613 op->v2 = v2->val;
614 op->inplace = NULL;
615 return new_address(t1->calc2(op), am);
616 }
617 break;
618 case T_CODE:
619 if (op->op != O_IN) {
620 return t1->calc2(op);
621 }
622 break;
623 case T_REGISTER:
624 if (Register(op->v1)->len == 1) {
625 am = register_to_indexing(Register(op->v1)->data[0]);
626 if (am == A_NONE) break;
627 if (op->op == O_ADD) {
628 return new_address(val_reference(v2->val), v2->type << 4 | am);
629 }
630 if (op->op == O_SUB) {
631 if (am == v2->type) {
632 op->v1 = int_value[0];
633 op->v2 = v2->val;
634 op->inplace = NULL;
635 return INT_OBJ->calc2(op);
636 }
637 }
638 }
639 break;
640 default: break;
641 }
642 if (v2->val == none_value || v2->val->obj == ERROR_OBJ) return val_reference(v2->val);
643 return obj_oper_error(op);
644 }
645
addressobj_init(void)646 void addressobj_init(void) {
647 new_type(&obj, T_ADDRESS, "address", sizeof(Address));
648 obj.convert = convert;
649 obj.destroy = destroy;
650 obj.garbage = garbage;
651 obj.same = same;
652 obj.truth = truth;
653 obj.hash = hash;
654 obj.repr = repr;
655 obj.str = str;
656 obj.address = address;
657 obj.ival = ival;
658 obj.uval = uval;
659 obj.uval2 = uval2;
660 obj.iaddress = iaddress;
661 obj.uaddress = uaddress;
662 obj.sign = sign;
663 obj.function = function;
664 obj.calc1 = calc1;
665 obj.calc2 = calc2;
666 obj.rcalc2 = rcalc2;
667 obj.slice = slice;
668 }
669
addressobj_names(void)670 void addressobj_names(void) {
671 new_builtin("address", val_reference(Obj(ADDRESS_OBJ)));
672 }
673