1 /*
2 * property.c
3 *
4 * Property manipulation routines
5 *
6 */
7
8 #include "ztypes.h"
9
10 /*
11 * get_property_addr
12 *
13 * Calculate the address of the start of the property list associated with an
14 * object.
15 *
16 */
17
18 #ifdef __STDC__
get_property_addr(zword_t obj)19 static zword_t get_property_addr (zword_t obj)
20 #else
21 static zword_t get_property_addr (obj)
22 zword_t obj;
23 #endif
24 {
25 zword_t offset, prop;
26
27 /* Calculate the address of the property pointer in the object */
28
29 offset = get_object_address (obj);
30 offset += (h_type < V4) ? O3_PROPERTY_OFFSET : O4_PROPERTY_OFFSET;
31
32 /* Read the property pointer */
33
34 prop = get_word (offset);
35
36 /* Skip past object description which is an ASCIC of encoded words */
37
38 prop += (get_byte (prop) * 2) + 1;
39
40 return (prop);
41
42 }/* get_property_adr */
43
44 /*
45 * get_next_property
46 *
47 * Calculate the address of the next property in a property list.
48 *
49 */
50
51 #ifdef __STDC__
get_next_property(zword_t propp)52 static zword_t get_next_property (zword_t propp)
53 #else
54 static zword_t get_next_property (propp)
55 zword_t propp;
56 #endif
57 {
58 zbyte_t value;
59
60 /* Load the current property id */
61
62 value = get_byte (propp++);
63
64 /* Calculate the length of this property */
65
66 if (h_type < V4)
67 value = (zbyte_t) ((value & property_size_mask) >> 5);
68 else if (value & 0x80) {
69 value = get_byte (propp) & (zbyte_t) property_size_mask;
70 if (value == 0)
71 value = 64;
72 }
73 else if (value & 0x40)
74 value = 1;
75 else
76 value = 0;
77
78 /* Address property length + 1 to current property pointer */
79
80 return ((zword_t) (propp + value + 1));
81
82 }/* get_next_property */
83
84 /*
85 * load_property
86 *
87 * Load a property from a property list. Properties are held in list sorted by
88 * property id, with highest ids first. There is also a concept of a default
89 * property for loading only. The default properties are held in a table pointed
90 * to be the object pointer, and occupy the space before the first object.
91 *
92 */
93
94 #ifdef __STDC__
load_property(zword_t obj,zword_t prop)95 void load_property (zword_t obj, zword_t prop)
96 #else
97 void load_property (obj, prop)
98 zword_t obj;
99 zword_t prop;
100 #endif
101 {
102 zword_t propp;
103
104 #ifdef STRICTZ
105 if (obj == 0) {
106 report_strictz_error(STRZERR_GET_PROP,
107 "@get_prop called with object 0");
108 store_operand (0);
109 return;
110 }
111 #endif
112
113 /* Load address of first property */
114
115 propp = get_property_addr (obj);
116
117 /* Scan down the property list while the target property id is less than the
118 property id in the list */
119
120 while ((zbyte_t) (get_byte (propp) & property_mask) > (zbyte_t) prop)
121 propp = get_next_property (propp);
122
123 /* If the property ids match then load the first property */
124
125 if ((zbyte_t) (get_byte (propp) & property_mask) == (zbyte_t) prop) {
126
127 /* Only load first property if it is a byte sized property */
128
129 if ((get_byte (propp++) & property_size_mask) == 0) {
130 store_operand (get_byte (propp));
131 return;
132 }
133 } else
134
135 /* Calculate the address of the default property */
136
137 propp = h_objects_offset + ((prop - 1) * 2);
138
139 /* Load the first property word */
140
141 store_operand (get_word (propp));
142
143 }/* load_property */
144
145 /*
146 * store_property
147 *
148 * Store a property value in a property list. The property must exist in the
149 * property list to be replaced.
150 *
151 */
152
153 #ifdef __STDC__
store_property(zword_t obj,zword_t prop,zword_t value)154 void store_property (zword_t obj, zword_t prop, zword_t value)
155 #else
156 void store_property (obj, prop, value)
157 zword_t obj;
158 zword_t prop;
159 zword_t value;
160 #endif
161 {
162 zword_t propp;
163
164 #ifdef STRICTZ
165 if (obj == 0) {
166 report_strictz_error(STRZERR_PUT_PROP,
167 "@put_prop called with object 0");
168 return;
169 }
170 #endif
171
172 /* Load address of first property */
173
174 propp = get_property_addr (obj);
175
176 /* Scan down the property list while the target property id is less than the
177 property id in the list */
178
179 while ((zbyte_t) (get_byte (propp) & property_mask) > (zbyte_t) prop)
180 propp = get_next_property (propp);
181
182 /* If the property id was found then store a new value, otherwise complain */
183
184 if ((zbyte_t) (get_byte (propp) & property_mask) == (zbyte_t) prop) {
185
186 /* Determine if this is a byte or word sized property */
187
188 if ((get_byte (propp++) & property_size_mask) == 0)
189 set_byte (propp, value);
190 else
191 set_word (propp, value);
192 } else
193 fatal ("No such property");
194
195 }/* store_property */
196
197 /*
198 * load_next_property
199 *
200 * Load the property after the current property. If the current property is zero
201 * then load the first property.
202 *
203 */
204
205 #ifdef __STDC__
load_next_property(zword_t obj,zword_t prop)206 void load_next_property (zword_t obj, zword_t prop)
207 #else
208 void load_next_property (obj, prop)
209 zword_t obj;
210 zword_t prop;
211 #endif
212 {
213 zword_t propp;
214
215 #ifdef STRICTZ
216 if (obj == 0) {
217 report_strictz_error(STRZERR_GET_NEXT_PROP,
218 "@get_next_prop called with object 0");
219 store_operand (0);
220 return;
221 }
222 #endif
223
224 /* Load address of first property */
225
226 propp = get_property_addr (obj);
227
228 /* If the property id is non zero then find the next property */
229
230 if (prop) {
231
232 /* Scan down the property list while the target property id is less than the
233 property id in the list */
234
235 while ((zbyte_t) (get_byte (propp) & property_mask) > (zbyte_t) prop)
236 propp = get_next_property (propp);
237
238 /* If the property id was found then get the next property, otherwise complain */
239
240 if ((zbyte_t) (get_byte (propp) & property_mask) == (zbyte_t) prop)
241 propp = get_next_property (propp);
242 else
243 fatal ("No such property");
244 }
245
246 /* Return the next property id */
247
248 store_operand (get_byte (propp) & property_mask);
249
250 }/* load_next_property */
251
252 /*
253 * load_property_address
254 *
255 * Load the address address of the data associated with a property.
256 *
257 */
258
259 #ifdef __STDC__
load_property_address(zword_t obj,zword_t prop)260 void load_property_address (zword_t obj, zword_t prop)
261 #else
262 void load_property_address (obj, prop)
263 zword_t obj;
264 zword_t prop;
265 #endif
266 {
267 zword_t propp;
268
269 #ifdef STRICTZ
270 if (obj == 0) {
271 report_strictz_error(STRZERR_GET_PROP_ADDR,
272 "@get_prop_addr called with object 0");
273 store_operand (0);
274 return;
275 }
276 #endif
277
278 /* Load address of first property */
279
280 propp = get_property_addr (obj);
281
282 /* Scan down the property list while the target property id is less than the
283 property id in the list */
284
285 while ((zbyte_t) (get_byte (propp) & property_mask) > (zbyte_t) prop)
286 propp = get_next_property (propp);
287
288 /* If the property id was found then calculate the property address, otherwise return zero */
289
290 if ((zbyte_t) (get_byte (propp) & property_mask) == (zbyte_t) prop) {
291
292 /* Skip past property id, can be a byte or a word */
293
294 if (h_type > V3 && (get_byte (propp) & 0x80))
295 propp++;
296 propp++;
297 store_operand (propp);
298 } else
299
300 /* No property found, just return 0 */
301
302 store_operand (0);
303
304 }/* load_property_address */
305
306 /*
307 * load_property_length
308 *
309 * Load the length of a property.
310 *
311 */
312
313 #ifdef __STDC__
load_property_length(zword_t propp)314 void load_property_length (zword_t propp)
315 #else
316 void load_property_length (propp)
317 zword_t propp;
318 #endif
319 {
320
321 /* Back up the property pointer to the property id */
322
323 propp--;
324
325 if (h_type < V4)
326
327 /* Property length is in high bits of property id */
328
329 store_operand (((get_byte (propp) & property_size_mask ) >> 5) + 1);
330 else if (get_byte (propp) & 0x80) {
331
332 /* Property length is in property id */
333 int val = get_byte (propp) & property_size_mask;
334 if (val == 0)
335 val = 64;
336 store_operand (val);
337 }
338 else
339
340 /* Word sized property if bit 6 set, else byte sized property */
341
342 store_operand ((get_byte (propp) & 0x40) ? 2 : 1);
343
344 }/* load_property_length */
345
346 /*
347 * scan_data
348 *
349 * Scan an array of bytes or words looking for a target byte or word. The
350 * optional 4th parameter can set the address step and also whether to scan a
351 * byte array.
352 *
353 */
354
355 #ifdef __STDC__
scan_data(int argc,zword_t * argv)356 void scan_data (int argc, zword_t *argv)
357 #else
358 void scan_data (argc, argv)
359 int argc;
360 zword_t *argv;
361 #endif
362 {
363 unsigned long address;
364 unsigned int i, step;
365
366 /* Supply default parameters */
367
368 if (argc < 4)
369 argv[3] = 0x82;
370
371 address = argv[1];
372 step = argv[3];
373
374 /* Check size bit (bit 7 of step, 1 = word, 0 = byte) */
375
376 if (step & 0x80) {
377
378 step &= 0x7f;
379
380 /* Scan down an array for count words looking for a match */
381
382 for (i = 0; i < argv[2]; i++) {
383
384 /* If the word was found store its address and jump */
385
386 if (read_data_word (&address) == argv[0]) {
387 store_operand ((zword_t) (address - 2));
388 conditional_jump (TRUE);
389 return;
390 }
391
392 /* Back up address then step by increment */
393
394 address = (address - 2) + step;
395
396 }
397
398 } else {
399
400 step &= 0x7f;
401
402 /* Scan down an array for count bytes looking for a match */
403
404 for (i = 0; i < argv[2]; i++) {
405
406 /* If the byte was found store its address and jump */
407
408 if ((zword_t) read_data_byte (&address) == (zword_t) argv[0]) {
409 store_operand ((zword_t) (address - 1));
410 conditional_jump (TRUE);
411 return;
412 }
413
414 /* Back up address then step by increment */
415
416 address = (address - 1) + step;
417
418 }
419
420 }
421
422 /* If the data was not found store zero and jump */
423
424 store_operand (0);
425 conditional_jump (FALSE);
426
427 }/* scan_data */
428
429 /*
430 * move_data
431 *
432 */
433
434 #ifdef __STDC__
move_data(zword_t src,zword_t dst,zword_t count)435 void move_data (zword_t src, zword_t dst, zword_t count)
436 #else
437 void move_data (src, dst, count)
438 zword_t src;
439 zword_t dst;
440 zword_t count;
441 #endif
442 {
443 unsigned long address;
444 unsigned int i;
445
446 /* Catch no-op move case */
447
448 if (src == dst || count == 0)
449 return;
450
451 /* If destination address is zero then fill source with zeros */
452
453 if (dst == 0) {
454 for (i = 0; i < count; i++)
455 store_byte (src++, 0, 0);
456 return;
457 }
458
459 address = src;
460
461 if ((short) count < 0) {
462 while (count++)
463 store_byte (dst++, 0, read_data_byte (&address));
464 } else {
465 address += (unsigned long) count;
466 dst += count;
467 while (count--) {
468 address--;
469 store_byte (--dst, 0, read_data_byte (&address));
470 address--;
471 }
472 }
473
474 }/* move_data */
475
476 /*
477 * load_word
478 *
479 * Load a word from an array of words
480 *
481 */
482
483 #ifdef __STDC__
load_word(zword_t addr,zword_t offset)484 void load_word (zword_t addr, zword_t offset)
485 #else
486 void load_word (addr, offset)
487 zword_t addr;
488 zword_t offset;
489 #endif
490 {
491 unsigned long address;
492
493 /* Calculate word array index address */
494
495 address = addr + (offset * 2);
496
497 /* Store the byte */
498
499 store_operand (read_data_word (&address));
500
501 }/* load_word */
502
503 /*
504 * load_byte
505 *
506 * Load a byte from an array of bytes
507 *
508 */
509
510 #ifdef __STDC__
load_byte(zword_t addr,zword_t offset)511 void load_byte (zword_t addr, zword_t offset)
512 #else
513 void load_byte (addr, offset)
514 zword_t addr;
515 zword_t offset;
516 #endif
517 {
518 unsigned long address;
519
520 /* Calculate byte array index address */
521
522 address = addr + offset;
523
524 /* Load the byte */
525
526 store_operand (read_data_byte (&address));
527
528 }/* load_byte */
529
530 /*
531 * store_word
532 *
533 * Store a word in an array of words
534 *
535 */
536
537 #ifdef __STDC__
store_word(zword_t addr,zword_t offset,zword_t value)538 void store_word (zword_t addr, zword_t offset, zword_t value)
539 #else
540 void store_word (addr, offset, value)
541 zword_t addr;
542 zword_t offset;
543 zword_t value;
544 #endif
545 {
546
547 /* Calculate word array index address */
548
549 addr += offset * 2;
550
551 /* Check we are not writing outside of the writeable data area */
552
553 if (addr > data_size)
554 fatal ("Attempted write out of data area");
555
556 /* Store the word */
557
558 set_word (addr, value);
559
560 }/* store_word */
561
562 /*
563 * store_byte
564 *
565 * Store a byte in an array of bytes
566 *
567 */
568
569 #ifdef __STDC__
store_byte(zword_t addr,zword_t offset,zword_t value)570 void store_byte (zword_t addr, zword_t offset, zword_t value)
571 #else
572 void store_byte (addr, offset, value)
573 zword_t addr;
574 zword_t offset;
575 zword_t value;
576 #endif
577 {
578
579 /* Calculate byte array index address */
580
581 addr += offset;
582
583 /* Check we are not writing outside of the writeable data area */
584
585 if (addr > data_size)
586 fatal ("Attempted write out of data area");
587
588 /* Store the byte */
589
590 set_byte (addr, value);
591
592 }/* store_byte */
593