/// MISCELLANEOUS INSTRUCTIONS
-// case x0 (0633): // rccl
-// // 00...0 -> C(AQ)0,19
-// // C(calendar clock) -> C(AQ)20,71
-// {
+ case x0 (0633): // rccl
+ // 00...0 -> C(AQ)0,19
+ // C(calendar clock) -> C(AQ)20,71
+ {
//// XXX see ticket #23
// // For the rccl instruction, the first 2 or 3 bits of the addr
// // field of the instruction are used to specify which SCU.
// HDBGRegQ ();
// if (rc > 0)
// return rc;
-//#ifndef SPEED
-// if_sim_debug (DBG_TRACEEXT, & cpu_dev)
-// {
-// // Clock at initialization
-// // date -d "Tue Jul 22 16:39:38 PDT 1999" +%s
-// // 932686778
-// uint64 UnixSecs = 932686778;
-// uint64 UnixuSecs = UnixSecs * 1000000LL;
-// // now determine uSecs since Jan 1, 1901 ...
-// uint64 MulticsuSecs = 2177452800000000LL + UnixuSecs;
-//
-// // Back into 72 bits
-// word72 big = convert_to_word72 (cpu.rA, cpu.rQ);
-//#ifdef NEED_128
-// // Convert to time since boot
-// big = subtract_128 (big, construct_128 (0, MulticsuSecs));
-// uint32_t remainder;
-// uint128 bigsecs = divide_128_32 (big, 1000000u, & remainder);
-// uint64_t uSecs = remainder;
-// uint64_t secs = bigsecs.l;
-// sim_debug (DBG_TRACEEXT, & cpu_dev,
-// "Clock time since boot %4llu.%06llu seconds\n",
-// secs, uSecs);
-//#else
-// // Convert to time since boot
-// big -= MulticsuSecs;
-// unsigned long uSecs = big % 1000000u;
-// unsigned long secs = (unsigned long) (big / 1000000u);
-// sim_debug (DBG_TRACEEXT, & cpu_dev,
-// "Clock time since boot %4lu.%06lu seconds\n",
-// secs, uSecs);
-//#endif
-// }
-//#endif
-// }
-// break;
+#ifndef SPEED
+ if_sim_debug (DBG_TRACEEXT, & cpu_dev)
+ {
+ // Clock at initialization
+ // date -d "Tue Jul 22 16:39:38 PDT 1999" +%s
+ // 932686778
+ uint64 UnixSecs = 932686778;
+ uint64 UnixuSecs = UnixSecs * 1000000LL;
+ // now determine uSecs since Jan 1, 1901 ...
+ uint64 MulticsuSecs = 2177452800000000LL + UnixuSecs;
+
+ // Back into 72 bits
+ word72 big = convert_to_word72 (cpu.rA, cpu.rQ);
+#ifdef NEED_128
+ // Convert to time since boot
+ big = subtract_128 (big, construct_128 (0, MulticsuSecs));
+ uint32_t remainder;
+ uint128 bigsecs = divide_128_32 (big, 1000000u, & remainder);
+ uint64_t uSecs = remainder;
+ uint64_t secs = bigsecs.l;
+ sim_debug (DBG_TRACEEXT, & cpu_dev,
+ "Clock time since boot %4llu.%06llu seconds\n",
+ secs, uSecs);
+#else
+ // Convert to time since boot
+ big -= MulticsuSecs;
+ unsigned long uSecs = big % 1000000u;
+ unsigned long secs = (unsigned long) (big / 1000000u);
+ sim_debug (DBG_TRACEEXT, & cpu_dev,
+ "Clock time since boot %4lu.%06lu seconds\n",
+ secs, uSecs);
+#endif
+ }
+#endif
+ }
+ break;
case x0 (0002): // drl
// Causes a fault which fetches and executes, in absolute mode, the
"tape/word/system_library_unbundled/"
};
+#define N_SYSTEM_LINK 0x100
+int n_system_link;
+struct system_link {
+ struct system_link *next;
+ int n_words;
+ int offset;
+ char name[NAME_LEN];
+} system_link[N_SYSTEM_LINK];
+
#define N_LOADED_SEGMENT 0x100
int n_loaded_segment;
struct loaded_segment {
int segment;
int bitcount;
int linkage_offset;
+ struct system_link *system_link_head;
} loaded_segment[N_LOADED_SEGMENT];
#define N_SEGMENT 0x200
char *r = strchr(q, '\n');
if (r)
*r = 0;
- printf("xlate segname %s to %s\n", name, q);
+ fprintf(stderr, "xlate segname %s to %s\n", name, q);
return q;
}
}
fclose(fp);
}
- printf("can't xlate segname %s\n", name);
+ fprintf(stderr, "can't xlate segname %s\n", name);
return name;
}
rassert(p->name);
p->segment = allocate_segment();
- printf("load segname %s into segment %06o\n", name, p->segment);
+ fprintf(stderr, "load segname %s into segment %06o\n", name, p->segment);
loaded_segment_xref[p->segment] = p;
// search for segment in path
M[p->segment] = (word36 *)mmap(
NULL,
01000000 * sizeof(uint64_t),
- PROT_READ,
- MAP_SHARED,
+ PROT_READ | PROT_WRITE,
+ MAP_PRIVATE,
fd,
(off_t)0
);
found_bitcount:
;
+ // validate linkage header
struct object_map *object_map = get_object_map(p);
rassert(
object_map->linkage_length >=
sizeof(struct linkage_header) / sizeof(uint64_t)
);
+ struct virgin_linkage_header *virgin_linkage_header =
+ (struct virgin_linkage_header *)(
+ M[p->segment] + object_map->linkage_offset
+ );
+ rassert(virgin_linkage_header->def_offset == object_map->definition_offset);
+ rassert(virgin_linkage_header->first_ref_relp == 0);
+ rassert(virgin_linkage_header->static_length == object_map->static_length);
// copy and fill in linkage section
p->linkage_offset = allocate_linkage(object_map->linkage_length, 2);
+ fprintf(
+ stderr,
+ "allocate_linkage %06o$[%06o, %06o)\n",
+ linkage_segment,
+ p->linkage_offset,
+ p->linkage_offset + (int)object_map->linkage_length
+ );
+ if (strcmp(p->name, "hcs_") == 0)
+ // patch in .my_lp
+ *(struct its_pointer *)(M[p->segment] + 0312) = its_pointer(
+ linkage_segment,
+ p->linkage_offset
+ );
struct linkage_header *linkage_header = (struct linkage_header *)(
M[linkage_segment] + p->linkage_offset
);
memcpy(
linkage_header,
- M[p->segment] + object_map->linkage_offset,
+ virgin_linkage_header,
object_map->linkage_length * sizeof(uint64_t)
);
linkage_header->def_ptr = its_pointer(
isot[p->segment] = packed_pointer(linkage_segment, static_offset);
stack_header->cur_lot_size = next_segment;
+ p->system_link_head = NULL;
return p;
}
buf[len] = 0;
}
-int find_entry(
+struct its_pointer find_definition(
struct loaded_segment *p,
- const char *entry_segname,
- const char *entry_name,
+ const char *name,
+ int class,
bool entry
) {
struct object_map *object_map = get_object_map(p);
(uint64_t *)definition_header + definition->forward_relp
)
) {
+ rassert(definition->class <= CLASS_HEAP);
if (
- definition->class == CLASS_TEXT &&
+ definition->class != CLASS_SEGNAME &&
!definition->flags_ignore &&
+ (class == -1 || definition->class == class) &&
(!entry || definition->flags_entry)
) {
-#if 0 // arg_list_ptr_$arg_list_ptr_ should be wired_utility_$arg_list_ptr_
- struct segname_definition *segname_definition =
- (struct segname_definition *)(
- (uint64_t *)definition_header + definition->segname_relp
- );
- rassert(segname_definition->class == CLASS_SEGNAME);
-
- char segname[NAME_LEN];
+ char definition_name[NAME_LEN];
get_acc_string(
- (uint64_t *)definition_header + segname_definition->name_relp,
- segname,
- sizeof(segname)
+ (uint64_t *)definition_header + definition->name_relp,
+ definition_name,
+ sizeof(definition_name)
);
- if (strcmp(segname, entry_segname) == 0) {
-#endif
- char name[NAME_LEN];
- get_acc_string(
- (uint64_t *)definition_header + definition->name_relp,
- name,
- sizeof(name)
- );
-
- if (strcmp(name, entry_name) == 0)
- return (int)(object_map->text_offset + definition->thing_relp);
-#if 0
- }
-#endif
+ if (strcmp(definition_name, name) == 0)
+ switch (definition->class) {
+ case CLASS_TEXT:
+ return its_pointer(
+ p->segment,
+ (int)(object_map->text_offset + definition->thing_relp)
+ );
+ case CLASS_LINKAGE:
+ return its_pointer(
+ linkage_segment,
+ (int)(p->linkage_offset + definition->thing_relp)
+ );
+ default:
+ fprintf(
+ stderr,
+ "unimplemented class %s in definition %s$%s\n",
+ class_names[definition->class],
+ p->name,
+ name
+ );
+ exit(EXIT_FAILURE);
+ }
}
}
fprintf(
stderr,
- "can't find entry %s$%s in segment %s\n",
- entry_segname,
- entry_name,
- p->name
+ "can't find definition %s$%s\n",
+ p->name,
+ name
);
exit(EXIT_FAILURE);
}
// callback from simulator when fault type 2 occurs
-bool snap_link(void) {
- printf(
+void snap_link(void) {
+ fprintf(
+ stderr,
"fault type 2 at %06o:%06o accessing %06o:%06o\n",
cpu.PPR.PSR,
cpu.PPR.IC,
);
// find segment of faulting instruction (for validation purposes)
- if (cpu.PPR.PSR >= N_SEGMENT)
- return false;
+ rassert(cpu.PPR.PSR < N_SEGMENT);
struct loaded_segment *p = loaded_segment_xref[cpu.PPR.PSR];
- if (p == NULL)
- return false;
+ rassert(p);
// validate link address, using read-only linkage section (safer)
struct object_map *object_map = get_object_map(p);
(struct virgin_linkage_header *)(
M[p->segment] + object_map->linkage_offset
);
- if (
- cpu.TPR.TSR != linkage_segment ||
- cpu.TPR.CA & 1 ||
- cpu.TPR.CA <
- p->linkage_offset + virgin_linkage_header->first_ref_relp ||
- cpu.TPR.CA >=
- p->linkage_offset + object_map->linkage_length
- )
- return false;
+ rassert(
+ cpu.TPR.TSR == linkage_segment &&
+ (cpu.TPR.CA & 1) == 0 &&
+ cpu.TPR.CA >=
+ p->linkage_offset + virgin_linkage_header->first_ref_relp &&
+ cpu.TPR.CA <
+ p->linkage_offset + object_map->linkage_length
+ );
// validate link, using read-only linkage section (safer)
int link_relp = (int)(cpu.TPR.CA - p->linkage_offset);
struct its_pointer *link = (struct its_pointer *)(
M[cpu.TPR.TSR] + cpu.TPR.CA
);
- if (memcmp(link, virgin_link, sizeof(struct link)))
- return false;
+ rassert(memcmp(link, virgin_link, sizeof(struct link)) == 0);
// look up link target
struct definition_header *definition_header = (struct definition_header *)(
struct type_pair *type_pair = (struct type_pair *)(
(uint64_t *)definition_header + exp_word->type_relp
);
+ //rassert(type_pair->trap_relp == 0);
rassert(
type_pair->type >= LINK_SELF_BASE &&
type_pair->type <= LINK_CREATE_IF_NOT_FOUND
);
// process link by type
+ char offsetname[NAME_LEN];
+ get_acc_string(
+ (uint64_t *)definition_header + type_pair->offsetname_relp,
+ offsetname,
+ sizeof(offsetname)
+ );
+
+ char segname[NAME_LEN];
+ static const int section_to_class[] = {
+ CLASS_TEXT,
+ CLASS_LINKAGE,
+ CLASS_SYMBOL,
+ -1,
+ CLASS_STATIC
+ };
switch (type_pair->type) {
case LINK_REFNAME_OFFSETNAME:
- {
- char segname[NAME_LEN];
- get_acc_string(
- (uint64_t *)definition_header + type_pair->segname_relp,
- segname,
- sizeof(segname)
- );
-
- char offsetname[NAME_LEN];
- get_acc_string(
- (uint64_t *)definition_header + type_pair->offsetname_relp,
+ rassert(type_pair->trap_relp == 0);
+ get_acc_string(
+ (uint64_t *)definition_header + type_pair->segname_relp,
+ segname,
+ sizeof(segname)
+ );
+ *link = find_definition(
+ load_segment(xlate_segment(segname)),
+ offsetname,
+ -1,
+ false
+ );
+ break;
+ case LINK_SELF_OFFSETNAME:
+ switch (type_pair->segname_relp) {
+ case SECTION_TEXT: // 0
+ case SECTION_LINK: // 1
+ case SECTION_SYMBOL: // 2
+ case SECTION_STATIC: // 4
+ rassert(type_pair->trap_relp == 0);
+ *link = find_definition(
+ p,
offsetname,
- sizeof(offsetname)
+ section_to_class[type_pair->segname_relp],
+ false
);
-
- struct loaded_segment *q = load_segment(xlate_segment(segname));
- *link = its_pointer(
- q->segment,
- find_entry(q, segname, offsetname, false)
- );
- link->modifier1 = virgin_link->modifier;
-
- printf(
- "snap link %06o:%06o -> %s$%s + %06o -> %06o:%06o\n",
- (int)cpu.TPR.TSR,
- (int)cpu.TPR.CA,
- segname,
- offsetname,
- (int)exp_word->expression,
- (int)link->segment,
- (int)link->address
+ break;
+ case SECTION_SYSTEM:
+ ;
+ struct link_init *link_init = (struct link_init *)(
+ (uint64_t *)definition_header + type_pair->trap_relp
);
+ rassert(link_init->n_words < 01000000);
+ rassert(link_init->type == INIT_NO_INIT);
+
+ {
+ struct system_link *q;
+ for (q = p->system_link_head; q; q = q->next)
+ if (strcmp(q->name, offsetname) == 0) {
+ rassert(q->n_words == (int)link_init->n_words);
+ goto found_system_link;
+ }
+
+ rassert(n_system_link < N_SYSTEM_LINK);
+ q = system_link + n_system_link++;
+ q->n_words = (int)link_init->n_words;
+ q->offset = allocate_linkage((int)link_init->n_words, 2);
+ strcpy(q->name, offsetname);
+
+ found_system_link:
+ *link = its_pointer(linkage_segment, q->offset);
+ }
+ break;
}
break;
default:
- rassert(false);
+ fprintf(
+ stderr,
+ "unimplemented link type %s\n",
+ link_type_names[type_pair->type - 1]
+ );
+ exit(EXIT_FAILURE);
}
- return true;
+ link->address += exp_word->expression;
+ link->modifier1 = virgin_link->modifier;
+ fprintf(
+ stderr,
+ "snap link %06o:%06o -> %s$%s + %06o -> %06o:%06o\n",
+ (int)cpu.TPR.TSR,
+ (int)cpu.TPR.CA,
+ type_pair->type == LINK_SELF_OFFSETNAME ?
+ symbolic_section_names[type_pair->segname_relp] :
+ segname,
+ offsetname,
+ (int)exp_word->expression,
+ (int)link->segment,
+ (int)link->address
+ );
}
int main(int argc, char **argv) {
// initialize CPU
sim_deb = stderr;
cpu_dev.dctrl =
- //DBG_TRACE |
+ DBG_TRACE |
//DBG_MSG |
//DBG_REGDUMPAQI |
//DBG_REGDUMPIDX |
//DBG_REGDUMPDSBR |
//DBG_REGDUMPFLT |
//DBG_REGDUMP |
- //DBG_REGDUMP |
//DBG_ADDRMOD |
//DBG_APPENDING |
//DBG_TRACEEXT |
// load pl1 operators
struct loaded_segment *p = load_segment(xlate_segment("pl1_operators_"));
- int operator_table_offset = find_entry(
+ struct its_pointer operator_table_pointer = find_definition(
p,
- "pl1_operators_",
"operator_table",
+ -1,
false
);
- stack_header->pl1_operators_ptr = its_pointer(
- p->segment,
- operator_table_offset
- );
- stack_header->call_op_ptr = its_pointer(
- p->segment,
- find_entry(p, "pl1_operators_", "alm_call", false)
+ stack_header->pl1_operators_ptr = operator_table_pointer;
+ stack_header->call_op_ptr = find_definition(
+ p,
+ "alm_call",
+ -1,
+ false
);
- stack_header->push_op_ptr = its_pointer(
- p->segment,
- find_entry(p, "pl1_operators_", "alm_push", false)
+ stack_header->push_op_ptr = find_definition(
+ p,
+ "alm_push",
+ -1,
+ false
);
- stack_header->return_op_ptr = its_pointer(
- p->segment,
- find_entry(p, "pl1_operators_", "alm_return", false)
+ stack_header->return_op_ptr = find_definition(
+ p,
+ "alm_return",
+ -1,
+ false
);
- stack_header->no_pop_op_ptr = its_pointer(
- p->segment,
- find_entry(p, "pl1_operators_", "alm_return_no_pop", false)
+ stack_header->no_pop_op_ptr = find_definition(
+ p,
+ "alm_return_no_pop",
+ -1,
+ false
);
- stack_header->entry_op_ptr = its_pointer(
- p->segment,
- find_entry(p, "pl1_operators_", "alm_entry", false)
+ stack_header->entry_op_ptr = find_definition(
+ p,
+ "alm_entry",
+ -1,
+ false
);
// create first stack frame
calling_stub[0] = 0000622700100L; // tsx0 pr0|402 call_ext_out_desc
calling_stub[1] = 0000026420400L; // emcall exit_emulation
- cpu.rA = (word36)(n_args + 1) << 19;
+ cpu.rA = (word36)(n_args_af) << 19;
cpu.rX[1] = arg_list_offset;
cpu.PR[0].RNR = 3;
- cpu.PR[0].SNR = p->segment;
- cpu.PR[0].WORDNO = operator_table_offset;
+ cpu.PR[0].SNR = operator_table_pointer.segment;
+ cpu.PR[0].WORDNO = operator_table_pointer.address;
- struct loaded_segment *q = load_segment(xlate_segment(entry_segname));
+ struct its_pointer entry_pointer = find_definition(
+ load_segment(xlate_segment(entry_segname)),
+ entry_name,
+ -1,
+ true
+ );
cpu.PR[2].RNR = 3;
- cpu.PR[2].SNR = q->segment;
- cpu.PR[2].WORDNO = find_entry(q, entry_segname, entry_name, true);
+ cpu.PR[2].SNR = entry_pointer.segment;
+ cpu.PR[2].WORDNO = entry_pointer.address;
cpu.PR[6].RNR = 3;
cpu.PR[6].SNR = stack_segment;