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