1 /* This file has been modified by Data General Corporation, November 1989. */
4 This file provides an abstract interface to "tdesc" information.
5 It is designed to be used in a uniform manner by several kinds
7 (1) code in live debugged process (e.g., a traceback routine)
8 (2) a separate-process debugger debugging a live process
9 (3) a separate-process debugger debugging a memory dump
12 * captures machine context
13 * partial: excludes memory
16 * make one for starters, chain in reverse order to previous ones
17 * representation: pointer to opaque
28 typedef int dc_boolean_t; /* range 0 .. 1 */
33 typedef int dc_tristate_t; /* range 0 .. 2 */
40 A word is 32 bits of information. In memory, a word is word-aligned.
42 A common and important use of dc_word_t is to represent values in the
43 target process, including (byte) addresses in the target process.
44 In this case, C arithmetic can be used to simulate machine address
45 arithmetic on the target. (Unsigned arithmetic is actually modulus
48 typedef unsigned int dc_word_t;
51 /* These bit operations number bits from 0 at the least significant end. */
52 #define bit_test(word,bit) ((word) & (1 << (bit))) /* returns 0 or other */
53 #define bit_value(word,bit) (((word) >> (bit)) & 1) /* returns 0 or 1 */
54 #define bit_set(word,bit) ((word) |= (1 << (bit)))
55 #define bit_clear(word,bit) ((word) &= ~(1 << (bit)))
56 #define bit_assign(word, bit, bool) \
57 if (bool) bit_set(word, bit); else bit_clear(word, bit)
63 /* The exactness of locations may not be certainly known. */
64 typedef dc_tristate_t dc_exactness_t;
68 The model includes five kinds of contexts. Because each context
69 has an associated region and frame, these describe region kinds
70 and frame kinds as well.
71 [more description needed]
72 Currently, only call contexts exist.
75 typedef int dc_kind_t; /* range 0 .. 4 */
76 #define DC_CALL_KIND 0
77 #define DC_SAVE_KIND 1
78 #define DC_EXCEPTION_KIND 2
79 #define DC_PROTECTION_KIND 3
80 #define DC_SPECIAL_KIND 4
81 #define DC_NUM_KINDS 5
83 #define DC_MIO_ENTRY_POINT (1<< 0)
84 #define DC_MIO_PROLOGUE_END (1<< 1)
85 #define DC_MIO_EPILOGUE_START (1<< 2)
86 #define DC_MIO_IMPLICIT_PROLOGUE_END (1<<16)
87 #define DC_MIO_LITERAL_ENTRY_POINT (1<<17)
88 #define DC_MIO_LITERAL_EPILOGUE_START (1<<18)
90 #define DC_MII_PRECEDING_TDESC_END (1<<0)
91 #define DC_MII_FOLLOWING_TDESC_START (1<<1)
93 typedef struct dc_debug_info {
94 unsigned int protocol; /* 1 for this structure */
96 unsigned int text_words_count;
97 dc_word_t text_words_ptr;
98 unsigned int data_words_count;
99 dc_word_t data_words_ptr;
103 typedef struct tdesc_hdr {
104 unsigned int map_protocol; /* 1 for this structure */
105 unsigned int end; /* address beyond end */
109 typedef struct tdesc_chunk_hdr {
111 int info_length : 22;
112 int info_alignment : 2;
113 unsigned int info_protocol;
114 dc_word_t start_address;
115 dc_word_t end_address;
119 typedef struct tdesc_chunk_info1 {
120 int variant : 8; /* 1 for this structure */
121 int register_save_mask : 17;
123 int return_address_info_discriminant : 1;
124 int frame_address_register : 5;
125 unsigned int frame_address_offset;
126 unsigned int return_address_info;
127 unsigned int register_save_offset;
128 } tdesc_chunk_info1_t;
131 typedef struct tdesc_chunk1 {
132 tdesc_chunk_hdr_t hdr;
133 tdesc_chunk_info1_t info;
137 typedef struct dc_mstate {
138 dc_word_t reg[32]; /* general registers */
148 typedef struct dc_map_info_in {
150 dc_word_t preceding_tdesc_end;
151 dc_word_t following_tdesc_start;
155 typedef struct dc_map_info_out {
157 dc_word_t entry_point;
158 dc_word_t prologue_end;
159 dc_word_t epilogue_start;
165 void error_fcn (env, continuable, message)
166 dc_word_t env; /* environment (arbitrary datum) */
167 dc_boolean_t continuable; /* whether error function may return */
168 char *message; /* string (no trailing newline) */
170 /* In the future, we probably want the error_fcn to be: */
171 void error_fcn (env, continuable, code, ...)
172 dc_word_t env; /* environment (arbitrary datum) */
173 dc_boolean_t continuable; /* whether error function may return */
174 int code; /* error code */
175 ... /* parameters to message associated
178 void read_fcn (env, memory, length, buffer)
179 dc_word_t env; /* environment (arbitrary datum) */
180 dc_word_t memory; /* start address in image */
181 int length; /* in bytes */
182 char *buffer; /* start address of buffer */
183 /* There are no alignment assumptions for the read function. */
185 void write_fcn (env, memory, length, buffer)
186 dc_word_t env; /* environment (arbitrary datum) */
187 dc_word_t memory; /* start address in image */
188 int length; /* in bytes */
189 char *buffer; /* start address of buffer */
190 /* There are no alignment assumptions for the write function. */
191 /* The write function is optional. It must be provided if changes
192 to writable registers are to be made. */
194 void exec_fcn (env, mstate)
195 dc_word_t env; /* environment (arbitrary datum) */
196 dc_mstate_t *mstate; /* machine state (read-write) */
197 /* The execute function is optional. It would be used (in the future)
198 by the implementation of a procedurally specified tdesc mechanism. */
206 #define NULL ((void *) 0)
209 extern char *malloc();
210 extern char *calloc();
215 At initialization, create a tdesc table from the tdesc info.
216 A tdesc table is simply a sorted array of tdesc elements.
217 A tdesc element is the last 6 words of the tdesc chunk.
218 We require that all tdesc chunks have info protocol 1.
221 typedef struct tdesc_elem {
222 dc_word_t start_address;
223 dc_word_t end_address;
224 tdesc_chunk_info1_t info;
227 typedef tdesc_elem_t *tdesc_table_t;
229 void dc_correct_cr_data();
231 int dc_compare_tdesc_elems (elem1, elem2)
234 dc_word_t s1, s2, e1, e2;
235 s1 = ((tdesc_elem_t *) elem1)->start_address;
236 s2 = ((tdesc_elem_t *) elem2)->start_address;
237 if (s1 < s2) return -1;
238 if (s1 > s2) return 1;
239 e1 = ((tdesc_elem_t *) elem1)->end_address;
240 e2 = ((tdesc_elem_t *) elem2)->end_address;
241 if (e1 < e2) return -1;
242 if (e1 > e2) return 1;
247 typedef struct handle_info {
248 dc_word_t debug_info_ptr;
253 void (*write_fcn)(); /* NULL => absent */
255 void (*exec_fcn)(); /* NULL => absent */
257 void (*map_fcn)(); /* NULL => absent */
259 tdesc_table_t tdesc_table;
260 int tdesc_table_size;
263 typedef handle_info_t *dc_handle_t;
267 Errors detected in this module are funnelled through dc_error or dc_warn,
268 as appropriate. Both routines call dc_exception, which invokes the error
269 handler supplied by the user.
271 Currently, dc_exception substitutes parameters into the message given
272 it and passes the resulting string to the user error handler.
273 In the future, dc_exception should simply pass an error code and
274 the parameters on to the user error handler.
278 extern int vsprintf();
280 /* Exit status for exception-processing machinery failure */
281 #define DC_EXCEPTION_FAILURE 250
283 void dc_exception(continuable, args)
284 dc_boolean_t continuable;
291 handle = va_arg(args, dc_handle_t);
292 format = va_arg(args, char *);
293 (void) vsprintf(buffer, format, args);
294 (*(handle->error_fcn)) (handle->error_env, continuable, buffer);
296 exit(DC_EXCEPTION_FAILURE); /* User error handler should never return in this case. */
300 void dc_error(va_alist) /* (handle, format, args... ) */
306 dc_exception(DC_FALSE, args);
311 void dc_warn(va_alist) /* (handle, format, args... ) */
317 dc_exception(DC_TRUE, args);
323 #define MALLOC_FAILURE_MESSAGE "Heap space exhausted (malloc failed)."
324 #define CALLOC_FAILURE_MESSAGE "Heap space exhausted (Calloc failed)."
327 /* Commonize memory allocation call so failure diagnosis is easier */
329 char* dc_malloc( handle, size )
333 char* space = malloc( size );
334 if (space == (char *)NULL)
335 dc_error( handle, MALLOC_FAILURE_MESSAGE );
341 /* Commonize memory allocation call so failure diagnosis is easier */
343 char* dc_calloc( handle,nelem, size )
348 char* space = calloc( nelem, size );
349 if (space == (char *)NULL)
350 dc_error( handle, CALLOC_FAILURE_MESSAGE );
356 dc_word_t dc_read_word (handle, address)
361 (*(handle->read_fcn)) (handle->read_env, address,
362 sizeof(dc_word_t), (char *)(&(word)));
367 void dc_write_word (handle, address, value)
374 if (handle->write_fcn) {
375 (*(handle->write_fcn)) (handle->write_env, address,
376 sizeof(dc_word_t), (char *)(&(word)));
378 dc_error (handle, "Writing is disabled.");
383 void dc_write_masked_word (handle, address, mask, value)
389 dc_write_word (handle, address,
390 (value & mask) | (dc_read_word(handle, address) & ~mask));
394 dc_handle_t dc_initiate (debug_info_ptr,
395 error_fcn, error_env,
397 write_fcn, write_env,
400 dc_word_t debug_info_ptr;
405 void (*write_fcn)(); /* NULL => absent */
407 void (*exec_fcn)(); /* NULL => absent */
409 void (*map_fcn)(); /* NULL => absent */
411 /* write_fcn may be given as NULL if no writing is required. */
412 /* exec_fcn may be given as NULL if no execution is required.
413 Currently, no execution is required. It would be if the
414 implementation needed to invoke procedures in the debugged process. */
417 unsigned int debug_info_protocol;
418 dc_debug_info_t debug_info;
419 unsigned int tdesc_map_protocol;
420 tdesc_hdr_t tdesc_hdr;
421 dc_word_t tdesc_info_start;
422 dc_word_t tdesc_info_end;
423 dc_word_t tdesc_info_length;
425 /* Set up handle enough for dc_error. */
426 handle = (dc_handle_t) malloc(sizeof(handle_info_t));
427 /* Cant use dc_malloc() as handle is being created ... */
428 /* if (handle == NULL) (*error_fcn)( error_env, MALLOC_FAILURE_MESSAGE ) */
429 handle->error_fcn = error_fcn;
430 handle->error_env = error_env;
431 handle->read_fcn = read_fcn;
432 handle->read_env = read_env;
433 handle->write_fcn = write_fcn;
434 handle->write_env = write_env;
435 handle->exec_fcn = exec_fcn;
436 handle->exec_env = exec_env;
437 /****************************************************************/
438 /* BUG 9/19/89 Found by hls. Map functions not initialized. */
439 /****************************************************************/
440 handle->map_fcn = map_fcn;
441 handle->map_env = map_env;
442 handle->debug_info_ptr = debug_info_ptr;
443 handle->tdesc_table = (tdesc_table_t)NULL;
445 /* Find tdesc info. */
446 if (debug_info_ptr) {
447 (*read_fcn) (read_env, debug_info_ptr, sizeof(unsigned int),
448 (char *)(&debug_info_protocol));
449 if (debug_info_protocol != 1)
450 dc_error (handle, "Unrecognized debug info protocol: %d",
451 debug_info_protocol);
452 (*read_fcn) (read_env, debug_info_ptr, sizeof(dc_debug_info_t),
453 (char *)(&debug_info));
454 (*read_fcn) (read_env, debug_info.tdesc_ptr, sizeof(unsigned int),
455 (char *)(&tdesc_map_protocol));
456 if (tdesc_map_protocol != 1)
457 dc_error (handle, "Unrecognized tdesc map protocol: %d",
459 (*read_fcn) (read_env, debug_info.tdesc_ptr, sizeof(tdesc_hdr_t),
460 (char *)(&tdesc_hdr));
461 tdesc_info_start = debug_info.tdesc_ptr + sizeof(tdesc_hdr_t);
462 tdesc_info_end = tdesc_hdr.end;
463 tdesc_info_length = tdesc_info_end - tdesc_info_start;
465 /* Create tdesc table from tdesc info. */
467 /* Over-allocate in order to avoid second pass over tdesc info. */
468 tdesc_table_t tt = (tdesc_table_t) dc_malloc(handle, tdesc_info_length);
469 dc_word_t p = tdesc_info_start;
470 dc_word_t q = tdesc_info_end - sizeof(tdesc_chunk1_t);
472 tdesc_chunk1_t chunk;
473 dc_word_t start_address, end_address;
477 (*read_fcn) (read_env, p, sizeof(tdesc_chunk1_t), (char *)(&chunk));
478 if (chunk.hdr.zeroes != 0) {
480 p += sizeof(dc_word_t);
483 if (chunk.hdr.info_protocol != 1) {
484 dc_warn (handle, "Unrecognized tdesc info protocol: %d",
485 chunk.hdr.info_protocol);
488 if (chunk.hdr.info_length != 16) {
489 dc_warn (handle, "Incorrect tdesc info length: %d",
490 chunk.hdr.info_length);
493 if (chunk.hdr.info_alignment > 2) {
494 dc_warn (handle, "Incorrect tdesc info alignment: %d",
495 chunk.hdr.info_alignment);
498 start_address = chunk.hdr.start_address;
499 end_address = chunk.hdr.end_address;
500 if ((start_address&3)!=0) {
502 "Tdesc start address is not word-aligned: %#.8X",
506 if ((end_address&3)!=0) {
508 "Tdesc end address is not word-aligned: %#.8X",
512 if (start_address > end_address) {
513 /* Note that the range may be null. */
515 "Tdesc start address (%#.8X) follows end address (%#.8X).",
516 start_address, end_address);
519 if (chunk.info.variant != 1) {
520 dc_warn (handle, "Invalid tdesc chunk variant: %d",
524 if (chunk.info.pad1 != 0) {
525 dc_warn (handle, "Tdesc chunk padding is not zero.");
528 if (chunk.info.return_address_info_discriminant != 0) {
529 if ((chunk.info.return_address_info & 3) != 0) {
531 "Tdesc return address offset is not word-aligned: %#.8X",
532 chunk.info.return_address_info);
536 if ((chunk.info.return_address_info & ~31) != 0) {
538 "Invalid tdesc return address register: %d",
539 chunk.info.return_address_info);
543 if ((chunk.info.register_save_offset & 3) != 0) {
545 "Tdesc register save offset is not word-aligned: %#.8X",
546 chunk.info.register_save_offset);
550 tt[n].start_address = start_address;
551 tt[n].end_address = end_address;
552 tt[n].info = chunk.info;
556 p += sizeof(tdesc_chunk1_t);
558 /* Leftover (less than a tdesc_chunk1_t in size) is padding or
559 in error. Ignore it in either case. */
563 /* Sort table by start address. */
564 qsort ((char *)tt, n, sizeof(tdesc_elem_t), dc_compare_tdesc_elems);
566 /* Check for overlap among tdesc chunks. */
567 for (i=0; i<(n-1); i++) {
568 if (tt[i].end_address > tt[i+1].start_address)
569 dc_error (handle, "Text chunks overlap.");
573 /* Finish setting up handle. */
574 handle->tdesc_table = tt;
575 handle->tdesc_table_size = n;
578 handle->tdesc_table_size = 0;
581 return (dc_handle_t) handle;
585 void dc_terminate (handle)
588 if (((dc_handle_t)handle)->tdesc_table) {
589 free((char *)(((dc_handle_t)handle)->tdesc_table));
591 free((char *)handle);
600 For each interesting register (word-sized piece of machine state),
601 a word of value information is kept. This word may
602 be either the value of the register, or the address in
603 subject memory where the value can be found (and changed). In
604 addition, the register may be invalid (in which case the value
605 information is undefined). These three cases are encoded for
606 a given register in the same-numbered bit of two words of flags:
608 flags[0] bit flags[1] bit meaning
609 ------------ ------------ -------
610 0 0 register is invalid; info is undefined
611 0 1 register is readable; info is value
612 1 0 register is writable; info is address
615 The general registers (r0-r31) are handled by reg_info and
616 reg_flags. The bit number for a register is that register's number.
617 The other registers are grouped together for convenience and are
618 handled by aux_info and aux_flags. The bit numbers for these
630 The SXIP, SNIP, and SFIP are the exception-time values of the
631 XIP, NIP, and FIP registers. They are valid only in the topmost frame.
632 (That is, in any context obtained from dc_previous_context, they
635 "location" is a pseudo-register of this model and represents the
636 location of the context. It is always valid. It also has an
637 exactness associated with it. The location and its exactness of a
638 context obtained from dc_previous_context are taken from the
639 return address and its exactness of the context given as an argument
640 to dc_previous_context.
642 The following model is recommended for dealing with the partial
643 redundancy between location and the SXIP, SNIP, and SFIP values
644 in the topmost frame. The location should be set to either the
645 SNIP or SXIP value, and its exactness should be set to DC_NO. A
646 change to the register whose value the location is set to should
647 be accompanied by an identical change to the location.
649 The PSR is handled separately, because it is a diverse collection
650 of flags. The PSR, as a whole, is always valid. A separate
651 psr_ind flag tells whether the psr_info data is a value or
652 an address. Each bit of the PSR has its own pair of flag bits to
653 mark validity and writability.
658 /* The following value means "other", because state is stored in 2 bits. */
659 #define DC_RESERVED 3
662 #define RSTATE(flags, bit) \
663 ((bit_value((flags)[0], bit) << 1) + bit_value((flags)[1], bit))
665 #define REG_STATE(dcontext, reg) RSTATE(dcontext->reg_flags, reg)
666 #define AUX_STATE(dcontext, reg) RSTATE(dcontext->aux_flags, reg)
667 #define PSR_STATE(dcontext, reg) RSTATE(dcontext->psr_flags, reg)
670 #define SET_INVALID(flags, bit) \
671 { bit_clear ((flags)[0], bit); bit_clear ((flags)[1], bit); }
673 #define SET_READABLE(flags, bit) \
674 { bit_clear ((flags)[0], bit); bit_set ((flags)[1], bit); }
676 #define SET_WRITABLE(flags, bit) \
677 { bit_set ((flags)[0], bit); bit_clear ((flags)[1], bit); }
679 #define ASSIGN_RSTATE(to_flags, to_bit, from_flags, from_bit) \
680 { bit_assign ((to_flags)[0], to_bit, bit_value((from_flags)[0], from_bit));\
681 bit_assign ((to_flags)[1], to_bit, bit_value((from_flags)[1], from_bit));}
684 #define CHECK_REG_READ(dcontext, reg) \
685 if (REG_STATE(dcontext, reg) == DC_INVALID) \
686 dc_error (dcontext->handle, \
687 "General register %d is not readable.", reg)
689 #define CHECK_REG_WRITE(dcontext, reg) \
690 if (REG_STATE(dcontext, reg) != DC_WRITABLE) \
691 dc_error (dcontext->handle, \
692 "General register %d is not writable.", reg)
694 #define CHECK_AUX_READ(dcontext, reg) \
695 if (AUX_STATE(dcontext, reg) == DC_INVALID) \
696 dc_error (dcontext->handle, \
697 "Auxiliary register %d is not readable.", reg)
699 #define CHECK_AUX_WRITE(dcontext, reg) \
700 if (AUX_STATE(dcontext, reg) != DC_WRITABLE) \
701 dc_error (dcontext->handle, \
702 "Auxiliary register %d is not writable.", reg)
709 #define DC_NUM_REG 32
712 /* DC_AUX_LOC must be first, with value 0 */
713 #define DC_AUX_SXIP 1
714 #define DC_AUX_SNIP 2
715 #define DC_AUX_SFIP 3
716 #define DC_AUX_FPSR 4
717 #define DC_AUX_FPCR 5
722 #define CHECK_REG(dcontext, reg) \
723 if ((reg < 0) || (reg >= DC_NUM_REG)) \
724 dc_error (dcontext->handle, \
725 "Bad general register number: %d", reg)
727 #define CHECK_AUX(dcontext, reg) \
728 if ((reg < 1) || (reg >= DC_NUM_AUX)) \
729 dc_error (dcontext->handle, \
730 "Bad auxiliary register number: %d", reg)
731 /* CHECK_AUX is not used for location pseudo-register. */
733 #define CHECK_BIT(dcontext, bit) \
734 if ((bit < 0) || (bit >= 32)) \
735 dc_error (dcontext->handle, \
736 "Bad bit number: %d", bit)
740 typedef struct cr_value {
748 A "dc_cr_value" represents an execution-time value symbolically, in
749 terms of the initial value of a register (the value on entry to
750 the procedure being analyzed) and a known offset. A value with
751 a 'reg' field value of 0 through 31 represents the value obtained
752 by summing (using 32-bit modulus arithmetic) the initial value of
753 register 'reg' and the value 'off'. Note that the value (0,k)
754 represents the constant value k, that (31,0) represents the CFA, and
755 that (1,0) represents the return address. A value with a 'reg' field
756 of DC_UNDEF represents an indeterminable value; in this case the
757 'off' field is undefined. Other values of 'reg' are erroneous.
760 typedef struct cr_data {
761 dc_cr_value_t reg_val[DC_NUM_REG];
764 unsigned int where[DC_NUM_REG];
768 'cr_data' collects all the information needed to represent the
769 symbolic machine state during code reading.
771 The 'reg_val' array gives the current dc_cr_value for each register.
773 The 'saved', 'how', and 'where' fields combine to describe what
774 registers have been saved, and where. The 'saved' and 'how' fields
775 are implicitly bit arrays over 0..31, where the numbering is from
776 0 on the right. (Hence, 1<<r gives the mask for register r.)
777 If saved[r] is 0, the register is not saved, and how[r] and where[r]
778 are undefined. If saved[r] is 1, then how[r] tells whether register r
779 was saved in another register (how[r]==0) or in the frame (how[r]==1).
780 In the former case, where[r] gives the register number; in the latter
781 case, where[r] gives the frame position.
785 typedef int dc_register_state_t; /* range 0 to 2 */
788 #define DC_READABLE 1
789 #define DC_WRITABLE 2
794 typedef struct dcontext_info {
795 dc_handle_t handle; /* environment of context */
796 dc_word_t reg_info[DC_NUM_REG];
797 dc_word_t reg_flags[2];
798 dc_word_t aux_info[DC_NUM_AUX];
799 dc_word_t aux_flags[2];
800 dc_exactness_t loc_exact;
801 dc_word_t psr_info; /* value or address */
802 dc_word_t psr_ind; /* DC_TRUE iff address */
803 dc_word_t psr_flags[2]; /* per-PSR-bit flags */
804 unsigned int code_reading; /* no tdesc therefore must read code*/
806 tdesc_elem_t *tdesc_elem_ptr; /* locates tdesc chunk */
807 dc_cr_data_t *cr_data_ptr; /* or code reading data */
811 typedef dcontext_info_t *dc_dcontext_t;
813 dc_word_t dc_get_value (handle, info, flags, pos)
818 /* Assumes either DC_READABLE or DC_WRITABLE. */
820 if (bit_test(flags[0], pos)) {
821 /* DC_WRITABLE case */
822 return dc_read_word(handle, info[pos]);
824 /* DC_READABLE case */
829 void dc_set_value (handle, info, flags, pos, value)
835 /* Assumes DC_WRITABLE. */
837 dc_write_word(handle, info[pos], value);
841 #define GET_REG_VALUE(dcontext, reg) \
842 dc_get_value(dcontext->handle, dcontext->reg_info, dcontext->reg_flags, reg)
844 #define SET_REG_VALUE(dcontext, reg, value) \
845 dc_set_value(dcontext->handle, dcontext->reg_info, dcontext->reg_flags, reg, \
848 #define GET_AUX_VALUE(dcontext, reg) \
849 dc_get_value(dcontext->handle, dcontext->aux_info, dcontext->aux_flags, reg)
851 #define SET_AUX_VALUE(dcontext, reg, value) \
852 dc_set_value(dcontext->handle, dcontext->aux_info, dcontext->aux_flags, reg, \
857 void dc_check_dcontext (dc)
859 /* Check consistency of information supplied to make a dcontext. */
863 if ((REG_STATE(dc, 0) != DC_READABLE) || (dc->reg_info[0] != 0))
864 dc_error (dc->handle, "Register 0 is misspecified");
865 for (i = 1; i < DC_NUM_REG; i++)
866 if (REG_STATE(dc, i) == DC_RESERVED)
867 dc_error (dc->handle,
868 "State for general register %d is incorrect", i);
869 for (i = 0; i < DC_NUM_AUX; i++)
870 if (AUX_STATE(dc, i) == DC_RESERVED)
871 dc_error (dc->handle,
872 "State for auxiliary register %d is incorrect", i);
873 if (AUX_STATE(dc, DC_AUX_LOC) == DC_INVALID)
874 dc_error (dc->handle, "Location is specified as invalid");
875 if (GET_AUX_VALUE(dc, DC_AUX_LOC) == 0)
876 dc_error (dc->handle, "Location is zero.");
877 if (dc->loc_exact >= 3)
878 dc_error (dc->handle, "Location exactness is incorrectly specified: %d",
880 if (dc->psr_ind >= 2)
881 dc_error (dc->handle,
882 "PSR indirection flag is incorrectly specified: %d",
884 for (i = 0; i < 32; i++)
885 if (PSR_STATE(dc, i) == DC_RESERVED)
886 dc_error (dc->handle, "State for PSR bit %d is incorrect", i);
891 tdesc_elem_t * dc_tdesc_lookup (loc, tt, tt_size, map_info_in_ptr)
895 dc_map_info_in_t *map_info_in_ptr;
896 /* Return address of tdesc_elem_t for given location, or NULL if
897 there is no tdesc chunk for the location.
905 map_info_in_ptr->flags = 0;
906 return (tdesc_elem_t *)NULL;
911 if (loc >= tt[m].start_address)
916 if (loc >= tt[m].end_address) {
917 map_info_in_ptr->preceding_tdesc_end = tt[m].end_address;
919 map_info_in_ptr->following_tdesc_start = tt[m+1].start_address;
920 map_info_in_ptr->flags = DC_MII_PRECEDING_TDESC_END |
921 DC_MII_FOLLOWING_TDESC_START;
923 map_info_in_ptr->flags = DC_MII_PRECEDING_TDESC_END;
925 return (tdesc_elem_t *)NULL;
926 } else if (loc < tt[m].start_address) {
927 map_info_in_ptr->following_tdesc_start = tt[m].start_address;
928 map_info_in_ptr->flags = DC_MII_FOLLOWING_TDESC_START;
929 return (tdesc_elem_t *)NULL;
937 dc_dcontext_t dc_make_dcontext (handle,
939 aux_info, aux_flags, loc_exact,
940 psr_info, psr_ind, psr_flags)
942 dc_word_t reg_info[DC_NUM_REG];
943 dc_word_t reg_flags[2];
944 dc_word_t aux_info[DC_NUM_AUX];
945 dc_word_t aux_flags[2];
946 dc_exactness_t loc_exact;
948 dc_boolean_t psr_ind;
949 dc_word_t psr_flags[2];
951 dc_dcontext_t dc = (dc_dcontext_t) dc_malloc (handle, sizeof(dcontext_info_t));
953 dc_map_info_in_t map_info_in;
955 /* Fill in supplied content. */
956 dc->handle = ((dc_handle_t)handle);
957 for (i = 0; i < DC_NUM_REG; i++) dc->reg_info[i] = reg_info[i];
958 for (i = 0; i < 2; i++) dc->reg_flags[i] = reg_flags[i];
959 for (i = 0; i < DC_NUM_AUX; i++) dc->aux_info[i] = aux_info[i];
960 for (i = 0; i < 2; i++) dc->aux_flags[i] = aux_flags[i];
961 dc->loc_exact = loc_exact;
962 dc->psr_info = psr_info;
963 dc->psr_ind = psr_ind;
964 for (i = 0; i < 2; i++) dc->psr_flags[i] = psr_flags[i];
966 dc_check_dcontext(dc);
968 /* Find tdesc information for the text chunk. */
970 /***************************************************************/
971 /* BUG 8/16/89 Found by hls. Not zeroing EV bits of location. */
972 /* SHOULD USE dc_location()! */
973 /* dc_word_t loc = GET_AUX_VALUE(dc, DC_AUX_LOC); */
974 /***************************************************************/
975 dc_word_t loc = GET_AUX_VALUE(dc, DC_AUX_LOC) & ~3;
977 dc_tdesc_lookup(loc, ((dc_handle_t)handle)->tdesc_table,
978 ((dc_handle_t)handle)->tdesc_table_size,&map_info_in);
980 dc->code_reading = 0;
981 dc->info_ptr.tdesc_elem_ptr = tep;
983 dc->code_reading = 1;
984 if (!dc->handle->map_fcn) {
985 dc_error (dc->handle, "No tdesc information for %#.8X and no map function supplied.",loc);
987 /****************************************************************/
988 /* BUG 9/18/89 Found by hls. Not using dc_malloc() */
989 /* dc->info_ptr.cr_data_ptr= (dc_cr_data_t *)malloc(sizeof(dc_cr_data_t )); */
990 /****************************************************************/
991 dc->info_ptr.cr_data_ptr= (dc_cr_data_t *)dc_calloc(dc->handle,1,sizeof(dc_cr_data_t ));
992 dc_read_code(loc,dc,map_info_in,dc->info_ptr.cr_data_ptr);
996 return (dc_dcontext_t) dc;
1001 void dc_free_dcontext (dcontext)
1002 dc_dcontext_t dcontext;
1004 /****************************************************************/
1005 /* BUG 9/19/89 Found by hls. Freeing non-pointer value. */
1006 /* free((char *)dcontext->code_reading); */
1007 /****************************************************************/
1008 if (dcontext->code_reading)
1009 free((char *)dcontext->info_ptr.cr_data_ptr);
1010 free((char *)dcontext);
1015 dc_register_state_t dc_location_state (dcontext)
1016 dc_dcontext_t dcontext;
1018 return AUX_STATE(((dc_dcontext_t)dcontext), DC_AUX_LOC);
1022 dc_exactness_t dc_location_exactness (dcontext)
1023 dc_dcontext_t dcontext;
1025 return ((dc_dcontext_t)dcontext)->loc_exact;
1029 dc_word_t dc_location (dcontext)
1030 dc_dcontext_t dcontext;
1031 /* Return high 30 bits only. */
1033 /* Don't need: CHECK_AUX_READ (((dc_dcontext_t)dcontext), DC_AUX_LOC); */
1034 return GET_AUX_VALUE (((dc_dcontext_t)dcontext), DC_AUX_LOC) & ~3;
1038 dc_boolean_t dc_location_in_text_chunk( dcontext, value )
1039 dc_dcontext_t dcontext;
1042 /* Check that new location is still within same text chunk. */
1043 tdesc_elem_t *tep = ((dc_dcontext_t)dcontext)->info_ptr.tdesc_elem_ptr;
1044 /********************************************************************/
1045 /* Bug in predicate -- LS adjusted according to OCS documentation.. */
1046 /* if ((value < tep->start_address) || (value >= tep->end_address))*/
1047 /********************************************************************/
1048 if ((value >= tep->start_address) && (value < tep->end_address))
1056 void dc_set_location (dcontext, value)
1057 dc_dcontext_t dcontext;
1059 /* Set high 30 bits only. */
1061 if (dc_location_in_text_chunk( dcontext, value ) != DC_TRUE)
1062 dc_warn (((dc_dcontext_t)dcontext)->handle,
1063 "New location is not in same text chunk.");
1065 CHECK_AUX_WRITE (((dc_dcontext_t)dcontext), DC_AUX_LOC);
1066 dc_write_masked_word (((dc_dcontext_t)dcontext)->handle,
1067 ((dc_dcontext_t)dcontext)->aux_info[DC_AUX_LOC], ~3, value);
1072 dc_register_state_t dc_general_register_state (dcontext, reg)
1073 dc_dcontext_t dcontext;
1076 CHECK_REG (((dc_dcontext_t)dcontext), reg);
1077 return REG_STATE(((dc_dcontext_t)dcontext), reg);
1081 dc_word_t dc_general_register (dcontext, reg)
1082 dc_dcontext_t dcontext;
1085 CHECK_REG (((dc_dcontext_t)dcontext), reg);
1086 CHECK_REG_READ (((dc_dcontext_t)dcontext), reg);
1087 return GET_REG_VALUE(((dc_dcontext_t)dcontext), reg);
1091 void dc_set_general_register (dcontext, reg, value)
1092 dc_dcontext_t dcontext;
1096 CHECK_REG (((dc_dcontext_t)dcontext), reg);
1097 CHECK_REG_WRITE (((dc_dcontext_t)dcontext), reg);
1098 SET_REG_VALUE (((dc_dcontext_t)dcontext), reg, value);
1103 dc_register_state_t dc_auxiliary_register_state (dcontext, reg)
1104 dc_dcontext_t dcontext;
1107 CHECK_AUX (((dc_dcontext_t)dcontext), reg);
1108 return AUX_STATE(((dc_dcontext_t)dcontext), reg);
1112 dc_word_t dc_auxiliary_register (dcontext, reg)
1113 dc_dcontext_t dcontext;
1116 CHECK_AUX (((dc_dcontext_t)dcontext), reg);
1117 CHECK_AUX_READ (((dc_dcontext_t)dcontext), reg);
1118 return GET_AUX_VALUE(((dc_dcontext_t)dcontext), reg);
1122 void dc_set_auxiliary_register (dcontext, reg, value)
1123 dc_dcontext_t dcontext;
1127 CHECK_AUX (((dc_dcontext_t)dcontext), reg);
1128 CHECK_AUX_WRITE (((dc_dcontext_t)dcontext), reg);
1129 SET_AUX_VALUE (((dc_dcontext_t)dcontext), reg, value);
1134 dc_register_state_t dc_psr_register_bit_state (dcontext, bit)
1135 dc_dcontext_t dcontext;
1138 CHECK_BIT (((dc_dcontext_t)dcontext), bit);
1139 return PSR_STATE(((dc_dcontext_t)dcontext), bit);
1143 dc_word_t dc_psr_register (dcontext)
1144 dc_dcontext_t dcontext;
1146 if (((dc_dcontext_t)dcontext)->psr_ind) {
1147 return dc_read_word(((dc_dcontext_t)dcontext)->handle,
1148 ((dc_dcontext_t)dcontext)->psr_info);
1150 return ((dc_dcontext_t)dcontext)->psr_info;
1155 void dc_set_psr_register (dcontext, mask, value)
1156 dc_dcontext_t dcontext;
1159 /* Set bits of PSR corresponding to 1 bits in mask. */
1161 if (((dc_dcontext_t)dcontext)->psr_ind) {
1162 if (((((dc_dcontext_t)dcontext)->psr_flags[0] & mask) != mask) ||
1163 ((((dc_dcontext_t)dcontext)->psr_flags[1] & mask) != 0))
1164 dc_error (((dc_dcontext_t)dcontext)->handle,
1165 "Some PSR bits specified are not writable.");
1166 dc_write_masked_word (((dc_dcontext_t)dcontext)->handle,
1167 ((dc_dcontext_t)dcontext)->psr_info, mask, value);
1169 dc_error (((dc_dcontext_t)dcontext)->handle, "PSR is not writable.");
1175 dc_word_t dc_frame_address (dcontext)
1176 dc_dcontext_t dcontext;
1178 if (!dcontext->code_reading) {
1179 tdesc_elem_t *tep = ((dc_dcontext_t)dcontext)->info_ptr.tdesc_elem_ptr;
1180 return dc_general_register(dcontext,
1181 tep->info.frame_address_register) + tep->info.frame_address_offset;
1183 if (dcontext->info_ptr.cr_data_ptr->reg_val[DC_REG_FP].reg == DC_REG_SP) {
1184 return (dc_general_register(dcontext,DC_REG_FP)
1185 - dcontext->info_ptr.cr_data_ptr->reg_val[DC_REG_FP].off);
1187 if (dcontext->info_ptr.cr_data_ptr->reg_val[DC_REG_SP].reg == DC_REG_SP) {
1188 return (dc_general_register(dcontext,DC_REG_SP)
1189 - dcontext->info_ptr.cr_data_ptr->reg_val[DC_REG_SP].off);
1191 dc_error (((dc_dcontext_t)dcontext)->handle, "Cannot locate frame pointer.");
1197 dc_kind_t dc_context_kind (dcontext)
1198 dc_dcontext_t dcontext;
1200 return DC_CALL_KIND;
1206 /* operations valid for call contexts only */
1209 dc_register_state_t dc_return_address_state (dcontext)
1210 dc_dcontext_t dcontext;
1212 tdesc_elem_t *tep = ((dc_dcontext_t)dcontext)->info_ptr.tdesc_elem_ptr;
1215 if (!dcontext->code_reading) {
1216 if (tep->info.return_address_info_discriminant) {
1219 return REG_STATE(((dc_dcontext_t)dcontext), tep->info.return_address_info);
1223 if (bit_test(dcontext->info_ptr.cr_data_ptr->saved,DC_REG_RA)) {
1224 if (bit_test(dcontext->info_ptr.cr_data_ptr->how,DC_REG_RA)) {
1227 reg= dcontext->info_ptr.cr_data_ptr->where[DC_REG_RA];
1230 return REG_STATE(((dc_dcontext_t)dcontext),reg);
1237 dc_exactness_t dc_return_address_exactness (dcontext)
1238 dc_dcontext_t dcontext;
1244 dc_word_t dc_return_address (dcontext)
1245 dc_dcontext_t dcontext;
1246 /* Return high 30 bits only. */
1248 tdesc_elem_t *tep = ((dc_dcontext_t)dcontext)->info_ptr.tdesc_elem_ptr;
1249 dc_word_t rai = tep->info.return_address_info;
1253 if (!dcontext->code_reading) {
1254 if (tep->info.return_address_info_discriminant) {
1255 val = dc_read_word (((dc_dcontext_t)dcontext)->handle,
1256 dc_frame_address(dcontext) + rai);
1258 val = dc_general_register (dcontext, rai);
1262 if (bit_test(dcontext->info_ptr.cr_data_ptr->saved,reg)) {
1263 if (bit_test(dcontext->info_ptr.cr_data_ptr->how,reg)) {
1264 val = dc_read_word (((dc_dcontext_t)dcontext)->handle,
1265 dc_frame_address(dcontext) +
1266 (dcontext->info_ptr.cr_data_ptr->where[reg]));
1268 reg= dcontext->info_ptr.cr_data_ptr->where[DC_REG_RA];
1269 val = dc_general_register (dcontext, reg);
1272 val = dc_general_register (dcontext, reg);
1279 void dc_set_return_address (dcontext, value)
1280 dc_dcontext_t dcontext;
1282 /* Set high 30 bits only. */
1284 if (!dcontext->code_reading) {
1285 tdesc_elem_t *tep = ((dc_dcontext_t)dcontext)->info_ptr.tdesc_elem_ptr;
1286 dc_word_t rai = tep->info.return_address_info;
1288 if (tep->info.return_address_info_discriminant) {
1289 dc_write_masked_word (((dc_dcontext_t)dcontext)->handle,
1290 dc_frame_address(dcontext) + rai, ~3, value);
1292 dc_set_general_register (dcontext, rai,
1293 (value & ~3) | (dc_general_register(dcontext, rai) & 3));
1296 if (bit_test(dcontext->info_ptr.cr_data_ptr->saved,DC_REG_RA)) {
1297 if (bit_test(dcontext->info_ptr.cr_data_ptr->how,DC_REG_RA)) {
1298 dc_write_masked_word (((dc_dcontext_t)dcontext)->handle,
1299 dc_frame_address(dcontext)
1300 + dcontext->info_ptr.cr_data_ptr->where[DC_REG_RA], ~3, value);
1302 dc_set_general_register( dcontext,
1303 dcontext->info_ptr.cr_data_ptr->where[DC_REG_RA]);
1306 dc_set_general_register( dcontext,
1307 dcontext->info_ptr.cr_data_ptr->where[DC_REG_RA]);
1314 /* operations valid for save contexts only */
1320 /* operations valid for exception contexts only */
1323 void dc_get_exception_info (dcontext, handler, datum)
1324 dc_dcontext_t dcontext;
1328 dc_error (((dc_dcontext_t)dcontext)->handle,
1329 "dc_get_exception_info is not yet implemented.");
1334 /* operations valid for protection contexts only */
1337 void dc_get_protection_info (dcontext, handler, datum)
1338 dc_dcontext_t dcontext;
1342 dc_error (((dc_dcontext_t)dcontext)->handle,
1343 "dc_get_protection_info is not yet implemented.");
1348 /* operations valid for special contexts only */
1351 void dc_get_special_info (dcontext, kind, datum)
1352 dc_dcontext_t dcontext;
1356 dc_error (((dc_dcontext_t)dcontext)->handle,
1357 "dc_get_special_info is not yet implemented.");
1362 /* operations valid for all contexts (again) */
1365 dc_dcontext_t dc_previous_dcontext (dcontext)
1366 dc_dcontext_t dcontext;
1367 /* Return NULL if there is no previous context. */
1369 dc_dcontext_t old = (dc_dcontext_t) dcontext;
1370 dcontext_info_t new; /* to serve as temporary storage only */
1379 if (dc_return_address_state((dc_dcontext_t)old) == DC_INVALID)
1380 dc_error (old->handle, "Return address is invalid.");
1382 if (dc_return_address((dc_dcontext_t)old) == 0)
1383 return (dc_dcontext_t)NULL; /* end of the chain */
1385 /* Copy over old contents. */
1388 cfa = dc_frame_address(old);
1389 /* Restore stack pointer. */
1390 new.reg_info[DC_REG_SP] = cfa;
1391 SET_READABLE (new.reg_flags, DC_REG_SP);
1393 /* Invalidate temporary registers. */
1394 for (r = 1; r <= 13; r++) SET_INVALID (new.reg_flags, r);
1396 if (!old->code_reading) {
1397 tep = old->info_ptr.tdesc_elem_ptr;
1398 /* Restore preserved registers. */
1399 rsm = tep->info.register_save_mask;
1400 offset = cfa + tep->info.register_save_offset;
1401 for (r = 14; r <= 30; r++) {
1402 if (bit_test(rsm, 30-r)) {
1403 new.reg_info[r] = offset;
1404 SET_WRITABLE (new.reg_flags, r);
1405 offset += sizeof(dc_word_t);
1409 /* Set location from old return address. */
1410 rai = tep->info.return_address_info;
1411 if (tep->info.return_address_info_discriminant) {
1412 new.aux_info[DC_AUX_LOC] = cfa + rai;
1413 SET_WRITABLE (new.aux_flags, DC_AUX_LOC);
1415 new.aux_info[DC_AUX_LOC] = old->reg_info[rai];
1416 ASSIGN_RSTATE (new.aux_flags, DC_AUX_LOC, old->reg_flags, rai);
1419 cdp = old->info_ptr.cr_data_ptr;
1421 /* Restore preserved registers. */
1422 for (r = 14; r <= 30; r++) {
1423 if (bit_test(cdp->saved,r)) {
1424 if (bit_test(cdp->how,r)){ /* saved in the frame */
1425 new.reg_info[r] = cfa+cdp->where[r];
1426 SET_WRITABLE (new.reg_flags, r);
1427 } else { /* saved in the in a register */
1428 new.reg_info[r] = dc_general_register(old,cdp->where[r]);
1429 ASSIGN_RSTATE (new.aux_flags, r, old->reg_flags, cdp->where[r]);
1431 } /* not saved, therefore, already valid , no else*/
1434 /* Set location from old return address. */
1435 if (bit_test(cdp->saved,DC_REG_RA)) {
1436 if (bit_test(cdp->how,DC_REG_RA)){ /* saved in the frame */
1437 new.aux_info[DC_AUX_LOC] =
1438 new.reg_info[DC_REG_RA] = cfa+cdp->where[DC_REG_RA];
1439 SET_WRITABLE (new.reg_flags, DC_REG_RA);
1440 SET_WRITABLE (new.aux_flags, DC_AUX_LOC);
1441 } else { /* saved in the in a register */
1442 new.reg_info[DC_REG_RA] =
1443 new.aux_info[DC_AUX_LOC] =
1444 dc_general_register(old,cdp->where[DC_REG_RA]);
1445 ASSIGN_RSTATE (new.aux_flags, DC_AUX_LOC,
1446 old->reg_flags, cdp->where[DC_REG_RA]);
1448 } else { /* not saved, therefore, already valid , set DC_AUX_LOC only*/
1449 new.aux_info[DC_AUX_LOC] =
1450 dc_general_register(old,DC_REG_RA);
1451 ASSIGN_RSTATE (new.aux_flags, DC_AUX_LOC,
1452 old->reg_flags, DC_REG_RA);
1456 /* Invalidate instruction pointers. */
1457 SET_INVALID (new.aux_flags, DC_AUX_SXIP);
1458 SET_INVALID (new.aux_flags, DC_AUX_SNIP);
1459 SET_INVALID (new.aux_flags, DC_AUX_SFIP);
1461 /* No change to FCR registers. */
1463 /* No change to PSR register. */
1465 return dc_make_dcontext ((dc_handle_t)new.handle,
1466 new.reg_info, new.reg_flags,
1467 new.aux_info, new.aux_flags, new.loc_exact,
1468 new.psr_info, new.psr_ind, new.psr_flags);
1473 /* extensions for nonlocal goto */
1483 label_t dc_make_label (dcontext, location)
1484 dc_dcontext_t dcontext;
1491 /* procedure for reading code */
1493 dc_read_code(loc,dc,map_info_in,cdp)
1497 dc_map_info_in_t map_info_in;
1499 dc_map_info_out_t map_info_out;
1501 dc_boolean_t found_branch=DC_FALSE;
1504 (*dc->handle->map_fcn)(dc->handle->map_env,loc,map_info_in,&map_info_out);
1505 if (map_info_out.flags & DC_MIO_ENTRY_POINT
1506 && (!(map_info_in.flags & DC_MII_PRECEDING_TDESC_END)
1507 || map_info_out.entry_point >= map_info_in.preceding_tdesc_end
1508 || map_info_out.flags & DC_MIO_LITERAL_ENTRY_POINT)) {
1509 dc_init_cr_data(cdp,(tdesc_elem_t *)NULL);
1510 pc= map_info_out.entry_point;
1511 } else if (map_info_in.flags & DC_MII_PRECEDING_TDESC_END) {
1513 /* tdesc_lookup gets the tep for the preceeding tdesc information
1514 /* so we call it with one less than the preceding tdesc end since
1515 /* tdesc information is exclusive of the ending address
1517 dc_init_cr_data(cdp,
1518 dc_tdesc_lookup(map_info_in.preceding_tdesc_end-1,
1519 ((dc_handle_t)dc->handle)->tdesc_table,
1520 ((dc_handle_t)dc->handle)->tdesc_table_size,
1522 pc= map_info_in.preceding_tdesc_end;
1524 dc_error (dc->handle, "Insufficient information for code reading.");
1530 instr= dc_read_word(dc->handle,pc);
1531 found_branch= dc_decode_finds_branch(dc,instr);
1532 if ((map_info_out.flags & DC_MIO_PROLOGUE_END)
1533 && (pc==map_info_out.prologue_end)) {
1537 if (DC_MIO_IMPLICIT_PROLOGUE_END & map_info_out.flags) {
1540 dc_error (dc->handle, "Found branch before end of prologue.");
1544 if (!(map_info_out.flags & DC_MIO_LITERAL_EPILOGUE_START)
1545 && (map_info_out.epilogue_start >= loc
1546 || !(map_info_out.flags & DC_MIO_EPILOGUE_START))) {
1549 dc_correct_cr_data(cdp,dc->handle);
1550 for (pc=map_info_out.epilogue_start;pc<loc;pc+=4) {
1551 instr= dc_read_word(dc->handle,pc);
1552 if (dc_decode_finds_branch(dc,instr)) {
1562 dc_init_cr_data(cdp,tep)
1574 /* Start off with all registers undefined and none saved. */
1575 for (reg = 0; reg < DC_NUM_REG; reg++) {
1576 cdp->reg_val[reg].reg = DC_UNDEF;
1580 /* Overwrite with what tdesc element says. */
1582 cdp->reg_val[tep->info.frame_address_register].reg = DC_REG_SP;
1583 cdp->reg_val[tep->info.frame_address_register].off =
1584 - tep->info.frame_address_offset;
1586 rai = tep->info.return_address_info;
1587 raid = tep->info.return_address_info_discriminant;
1588 if (raid || rai != DC_REG_RA) {
1589 bit_set(cdp->saved,DC_REG_RA);
1590 bit_assign(cdp->how,DC_REG_RA,raid);
1591 cdp->where[DC_REG_RA] = rai;
1594 rsm = tep->info.register_save_mask;
1595 frpos = tep->info.register_save_offset;
1596 for (reg = 14; reg <= 30; reg++) {
1597 if (bit_test(rsm, 30-reg)) {
1598 bit_set(cdp->saved,reg);
1599 bit_set(cdp->how,reg);
1600 cdp->where[reg] = frpos;
1601 frpos += sizeof(dc_word_t);
1603 cdp->reg_val[reg].reg = reg;
1604 cdp->reg_val[reg].off = 0;
1608 cdp->reg_val[0].reg = 0; /* guarantee what hardware does */
1609 cdp->reg_val[0].off = 0;
1612 /* Each register has its own initial value. */
1613 for (reg = 0; reg < DC_NUM_REG; reg++) {
1614 cdp->reg_val[reg].reg = reg;
1615 cdp->reg_val[reg].off = 0;
1617 /* No register is yet saved. */
1622 void dc_correct_cr_data(cdp,handle)
1627 dc_word_t save_regs = 0; /* registers used to save others */
1628 for (r = 1; r < DC_REG_SP; r++) {
1629 if (bit_test(cdp->saved,r) && !bit_test(cdp->how,r)) {
1631 if (bit_test(save_regs,sr)) {
1632 dc_error(handle, "Same register used to save two others.");
1634 bit_set(save_regs,sr);
1637 for (r = 1; r < DC_REG_FP; r++) {
1638 if ((r < 14 || bit_test(cdp->saved,r)) && !bit_test(save_regs,r)) {
1639 cdp->reg_val[r].reg = DC_UNDEF;
1642 if (bit_test(cdp->saved,DC_REG_FP) &&
1643 cdp->reg_val[DC_REG_FP].reg == DC_REG_SP) { /* is r30 the far? */
1644 cdp->reg_val[DC_REG_SP].reg = DC_UNDEF; /* trash sp */
1645 } else if (cdp->reg_val[DC_REG_SP].reg == DC_REG_SP) { /* is r31 the far? */
1646 if (bit_test(cdp->saved,DC_REG_FP) && !bit_test(save_regs,DC_REG_FP)) {
1647 cdp->reg_val[DC_REG_FP].reg = DC_UNDEF; /* trash r30 */