11 #include "access_mode_values.h"
12 #include "area_info.h"
13 #include "definition_dcls.h"
14 #include "dps8/dps8.h"
15 #include "dps8/dps8_cpu.h"
16 #include "dps8/dps8_simh.h"
17 #include "dps8/dps8_sys.h"
18 //#include "iox_modes.h"
20 #include "object_map.h"
23 #include "stack_frame.h"
24 #include "stack_header.h"
27 #define DEBUG_NAME_LEN 0x100
28 #define LINE_LEN 0x100
29 #define PATH_LEN 0x1000
30 #define RESULT_LEN 0x400 // must be multiple of 4
35 uint64_t arg_count : 18;
39 uint64_t desc_count : 18;
42 struct its_pointer args[];
47 uint64_t number_dims : 4;
54 // dcl 01 based_entry aligned based,
57 struct its_pointer code_ptr;
59 struct its_pointer env_ptr;
62 // make these configurable later
63 const char *multics_root = "tape/word";
64 const char *multics_home = ">sim_home";
65 const char *multics_process = ">sim_process";
66 const char *search_path[] = {
67 ">library_dir_dir>system_library_1>execution",
69 ">system_library_3rd_party>C_COMPILER>executable",
70 ">system_library_obsolete",
71 ">system_library_standard",
72 ">system_library_tools",
73 ">system_library_unbundled"
75 #define N_SEARCH_PATH (sizeof(search_path) / sizeof(const char *))
77 #define N_SYSTEM_LINK 0x100
80 struct system_link *next;
83 char name[NAME_LEN + 1];
84 } system_link[N_SYSTEM_LINK];
86 #define N_DEBUG_SYMBOL 0x10000
91 } debug_symbol[N_DEBUG_SYMBOL];
93 struct debug_symbol debug_symbol_pl1_operators[] = {
94 #include "pl1_operators_.inc"
96 #define N_DEBUG_SYMBOL_PL1_OPERATORS \
97 (sizeof(debug_symbol_pl1_operators) / sizeof(struct debug_symbol))
99 #define N_KNOWN_SEGMENT 0x100
101 struct known_segment {
107 struct debug_symbol *debug_symbol;
108 struct system_link *system_link_head;
111 } known_segment[N_KNOWN_SEGMENT];
112 struct known_segment *hcs;
113 struct known_segment *iox;
114 struct known_segment *sys_info;
116 #define N_SEGMENT 0x200
118 struct known_segment *segment_to_known_segment[N_SEGMENT];
120 #define N_REF_NAME_TO_KNOWN_SEGMENT 0x400
121 int n_ref_name_to_known_segment;
122 struct ref_name_to_known_segment {
123 const char *ref_name;
124 struct known_segment *known_segment;
125 } ref_name_to_known_segment[N_REF_NAME_TO_KNOWN_SEGMENT];
128 int next_linkage_offset;
129 int emcall_stubs_offset;
130 struct packed_pointer *lot;
131 struct packed_pointer *isot;
134 int next_stack_offset;
135 struct stack_header *stack_header;
137 struct known_segment *iox;
138 struct its_pointer *user_input;
139 struct its_pointer *user_output;
140 struct its_pointer *error_output;
142 struct known_segment *error_table;
143 uint64_t *end_of_info;
144 uint64_t *long_record;
146 uint64_t *short_record;
148 jmp_buf exit_emulation;
150 void get_acc_string(uint64_t *acc_string, char *buf, int buf_len) {
151 int len = (acc_string[0] >> 27) & 0777;
152 rassert(len < buf_len);
154 static const int shifts[4] = {27, 18, 9, 0};
155 for (int i = 0, j = 1; i < len; ++i, ++j)
156 buf[i] = (char)(acc_string[j >> 2] >> shifts[j & 3]);
160 void get_string(char *buf, const uint64_t *string, int string_len) {
161 static const int shifts[4] = {27, 18, 9, 0};
162 for (int i = 0; i < string_len; ++i)
163 buf[i] = (char)(string[i >> 2] >> shifts[i & 3]);
167 void get_string_rstrip(char *buf, const uint64_t *string, int string_len) {
168 static const int shifts[4] = {27, 18, 9, 0};
169 for (int i = 0; i < string_len; ++i)
170 buf[i] = (char)(string[i >> 2] >> shifts[i & 3]);
171 while (string_len && buf[string_len - 1] == ' ')
176 int allocate_segment(void) {
177 rassert(n_segment < N_SEGMENT);
181 int scratch_segment(void) {
182 int segment = allocate_segment();
184 M[segment] = (word36 *)mmap(
186 01000000 * sizeof(uint64_t),
187 PROT_READ | PROT_WRITE,
188 MAP_ANONYMOUS | MAP_PRIVATE,
192 rassert(M[segment] != (word36 *)-1);
197 struct object_map *get_object_map(struct known_segment *p) {
198 rassert(p->bitcount % 36 == 0);
199 int wordcount = (p->bitcount / 36) & 0777777;
200 rassert(wordcount >= 1);
201 struct object_map *object_map = (struct object_map *)(
203 (M[p->segment][(wordcount - 1) & 0777777] >> 18) & 0777777
206 rassert(object_map->decl_vers == 2);
207 rassert(object_map->identifier[0] == 0157142152137); // 'obj_'
208 rassert(object_map->identifier[1] == 0155141160040); // 'map '
213 int allocate_linkage(int length, int align) {
215 next_linkage_offset = (next_linkage_offset + align) & ~align;
216 rassert(next_linkage_offset + length <= 01000000);
217 int offset = next_linkage_offset;
218 next_linkage_offset += length;
222 int allocate_stack(int length, int align) {
224 next_stack_offset = (next_stack_offset + align) & ~align;
225 rassert(next_stack_offset + length <= 01000000);
226 int offset = next_stack_offset;
227 next_stack_offset += length;
231 struct known_segment *make_known_segment(
232 const char *dir_name,
233 const char *entryname,
236 // construct path to directory, translating multics separators
237 int multics_root_len = strlen(multics_root);
238 int dir_name_len = strlen(dir_name);
240 rassert(multics_root_len + dir_name_len + 1 < PATH_LEN);
241 memcpy(path, multics_root, multics_root_len);
242 for (int i = 0; i < dir_name_len; ++i) {
244 path[multics_root_len + i] = c == '>' ? '/' : c == '/' ? '_' : c;
246 path[multics_root_len + dir_name_len] = '/';
248 // try to open directly
249 int entryname_len = strlen(entryname);
250 rassert(multics_root_len + dir_name_len + entryname_len < PATH_LEN);
251 strcpy(path + multics_root_len + dir_name_len + 1, entryname);
252 int fd = open(path, writeable ? O_RDWR : O_RDONLY);
255 // try to open via an alias
256 rassert(multics_root_len + dir_name_len + 1 + 6 < PATH_LEN);
257 strcpy(path + multics_root_len + dir_name_len + 1, ".xlate");
259 FILE *fp = fopen(path, "r");
262 while (fgets(line, sizeof(line), fp)) {
263 char *p = strchr(line, ' ');
266 if (strcmp(line, entryname) == 0) {
267 char *q = strchr(p, '\n');
270 int p_len = strlen(p);
271 rassert(multics_root_len + dir_name_len + 1 + p_len < PATH_LEN);
272 strcpy(path + multics_root_len + dir_name_len + 1, p);
273 fd = open(path, writeable ? O_RDWR : O_RDONLY);
276 fprintf(stderr, "xlate entryname %s to %s\n", entryname, p);
278 entryname_len = p_len;
290 // see if already known under the found path (can be tricked)
291 for (int i = 0; i < n_known_segment; ++i) {
292 struct known_segment *p = known_segment + i;
293 if (strcmp(p->path, path) == 0) {
299 // allocate table entries
300 rassert(n_known_segment < N_KNOWN_SEGMENT);
301 struct known_segment *p = known_segment + n_known_segment++;
302 p->path = strdup(path);
304 p->segment = allocate_segment();
305 fprintf(stderr, "load %s into segment %06o\n", path, p->segment);
306 segment_to_known_segment[p->segment] = p;
307 p->writeable = writeable;
310 M[p->segment] = (word36 *)mmap(
312 01000000 * sizeof(uint64_t),
313 PROT_READ | PROT_WRITE,
314 writeable ? 0 : MAP_PRIVATE,
318 rassert(M[p->segment] != (word36 *)-1);
321 // see if we can find bitcount for segment
322 rassert(multics_root_len + dir_name_len + 1 + 4 < PATH_LEN);
323 strcpy(path + multics_root_len + dir_name_len + 1, ".dir");
325 FILE *fp = fopen(path, "r");
328 while (fgets(line, sizeof(line), fp)) {
329 char *q = strchr(line, ' ');
332 if (strcmp(line, entryname) == 0) {
333 p->bitcount = (int)strtol(q, NULL, 0);
344 struct known_segment *initiate_segment(
345 const char *dir_name,
346 const char *entryname,
347 const char *ref_name,
351 // see if already known under this ref_name
352 for (int i = 0; i < n_ref_name_to_known_segment; ++i)
353 if (strcmp(ref_name_to_known_segment[i].ref_name, ref_name) == 0) {
356 return ref_name_to_known_segment[i].known_segment;
359 // try either given dir_name or search path
360 struct known_segment *p;
362 p = make_known_segment(dir_name, entryname, writeable);
367 for (int i = 0; i < N_SEARCH_PATH; ++i) {
368 p = make_known_segment(search_path[i], entryname, writeable);
370 goto found_search_path;
377 // make known under this ref_name
378 rassert(n_ref_name_to_known_segment < N_REF_NAME_TO_KNOWN_SEGMENT);
379 struct ref_name_to_known_segment *q =
380 ref_name_to_known_segment + n_ref_name_to_known_segment++;
381 q->ref_name = strdup(ref_name);
382 rassert(q->ref_name);
383 q->known_segment = p;
391 int compare_debug_symbol(const void *p, const void *q) {
393 ((const struct debug_symbol *)p)->offset <
394 ((const struct debug_symbol *)q)->offset ?
396 ((const struct debug_symbol *)p)->offset >
397 ((const struct debug_symbol *)q)->offset ?
400 ((const struct debug_symbol *)p)->name,
401 ((const struct debug_symbol *)q)->name
405 struct debug_symbol *find_debug_symbol(struct known_segment *p, int offset) {
406 for (int i = p->n_debug_symbol; --i >= 0; ) {
407 struct debug_symbol *q = p->debug_symbol + i;
408 if (q->offset <= offset)
409 return p->debug_symbol + i;
415 char *lookup_address(int segment, int offset) {
416 if (segment >= N_SEGMENT)
418 struct known_segment *p = segment_to_known_segment[segment];
422 struct debug_symbol *q = find_debug_symbol(p, offset);
426 static char text[DEBUG_NAME_LEN + 0x20];
427 int i = nesting & 0xf;
428 memset(text, ' ', i);
429 sprintf(text + i, "<%s + %06o>", q->name, offset - q->offset);
433 struct its_pointer find_definition(
434 struct known_segment *p,
439 // redirect specific entry points to emcall stubs
441 if (strcmp(name, "make_entry") == 0)
442 return its_pointer(linkage_segment, emcall_stubs_offset);
443 if (strcmp(name, "make_ptr") == 0)
444 return its_pointer(linkage_segment, emcall_stubs_offset + 3);
445 if (strcmp(name, "make_seg") == 0)
446 return its_pointer(linkage_segment, emcall_stubs_offset + 6);
447 if (strcmp(name, "proc_info") == 0)
448 return its_pointer(linkage_segment, emcall_stubs_offset + 9);
449 if (strcmp(name, "set_ips_mask") == 0)
450 return its_pointer(linkage_segment, emcall_stubs_offset + 12);
451 if (strcmp(name, "reset_ips_mask") == 0)
452 return its_pointer(linkage_segment, emcall_stubs_offset + 15);
453 if (strcmp(name, "fs_search_get_wdir") == 0)
454 return its_pointer(linkage_segment, emcall_stubs_offset + 18);
455 if (strcmp(name, "initiate_count") == 0)
456 return its_pointer(linkage_segment, emcall_stubs_offset + 21);
457 if (strcmp(name, "fs_get_mode") == 0)
458 return its_pointer(linkage_segment, emcall_stubs_offset + 24);
459 if (strcmp(name, "high_low_seg_count") == 0)
460 return its_pointer(linkage_segment, emcall_stubs_offset + 27);
462 strcmp(name, ".my_lp") &&
463 strcmp(name, "cpu_time_and_paging_") &&
464 strcmp(name, "get_authorization")
466 fprintf(stderr, "unsupported emcall hcs_$%s\n", name);
471 if (strcmp(name, "get_line") == 0)
472 return its_pointer(linkage_segment, emcall_stubs_offset + 30);
473 if (strcmp(name, "put_chars") == 0)
474 return its_pointer(linkage_segment, emcall_stubs_offset + 33);
476 strcmp(name, "user_input") &&
477 strcmp(name, "user_output") &&
478 strcmp(name, "error_output") &&
479 strcmp(name, "init_standard_iocbs") &&
480 strcmp(name, "syn_attach") &&
481 strcmp(name, "get_group_id_") &&
482 strcmp(name, "modes")
484 fprintf(stderr, "unsupported emcall iox_$%s\n", name);
488 else if (p == sys_info) {
489 if (strcmp(name, "service_system") == 0)
490 return its_pointer(linkage_segment, emcall_stubs_offset + 36);
493 struct object_map *object_map = get_object_map(p);
494 struct definition_header *definition_header = (struct definition_header *)(
495 M[p->segment] + object_map->definition_offset
499 struct definition *definition = (struct definition *)(
500 (uint64_t *)definition_header + definition_header->def_list_relp
502 *(uint64_t *)definition;
503 definition = (struct definition *)(
504 (uint64_t *)definition_header + definition->forward_relp
507 rassert(definition->class <= CLASS_HEAP);
509 definition->class != CLASS_SEGNAME &&
510 !definition->flags_ignore &&
511 (class == -1 || definition->class == class) &&
512 (!entry || definition->flags_entry)
514 char definition_name[NAME_LEN + 1];
516 (uint64_t *)definition_header + definition->name_relp,
521 if (strcmp(definition_name, name) == 0)
522 switch (definition->class) {
526 (int)(object_map->text_offset + definition->thing_relp)
531 (int)(p->linkage_offset + definition->thing_relp)
536 "unimplemented class %s in segment %s definition %s\n",
537 class_names[definition->class],
548 "can't find segment %s definition %s\n",
555 struct known_segment *link_segment(
556 const char *dir_name,
557 const char *entryname,
560 struct known_segment *p =
561 initiate_segment(dir_name, entryname, ref_name, false, NULL);
564 if (p->linkage_offset == 0) {
565 struct object_map *object_map = get_object_map(p);
567 // validate linkage header
569 object_map->linkage_length >=
570 sizeof(struct linkage_header) / sizeof(uint64_t)
572 struct virgin_linkage_header *virgin_linkage_header =
573 (struct virgin_linkage_header *)(
574 M[p->segment] + object_map->linkage_offset
576 rassert(virgin_linkage_header->def_offset == object_map->definition_offset);
577 rassert(virgin_linkage_header->first_ref_relp == 0);
578 rassert(virgin_linkage_header->static_length == object_map->static_length);
580 // copy and fill in linkage section
581 p->linkage_offset = allocate_linkage(object_map->linkage_length, 2);
584 "allocate_linkage %06o$[%06o, %06o)\n",
587 p->linkage_offset + (int)object_map->linkage_length
589 if (strcmp(ref_name, "hcs_") == 0) {
591 struct its_pointer my_lp_pointer = find_definition(
597 *(struct its_pointer *)(
598 M[my_lp_pointer.segment] + my_lp_pointer.offset
605 strcmp(ref_name, "iox_") == 0 ||
606 strcmp(ref_name, "get_group_id_") == 0
609 else if (strcmp(ref_name, "sys_info") == 0)
611 struct linkage_header *linkage_header = (struct linkage_header *)(
612 M[linkage_segment] + p->linkage_offset
616 virgin_linkage_header,
617 object_map->linkage_length * sizeof(uint64_t)
619 linkage_header->def_ptr = its_pointer(
621 object_map->definition_offset
623 linkage_header->symbol_ptr = packed_pointer(
625 object_map->symbol_offset
627 linkage_header->original_linkage_ptr = packed_pointer(
629 object_map->linkage_offset
631 linkage_header->stats_segment_number = linkage_segment;
633 // copy static section
634 int static_offset = allocate_linkage(object_map->static_length, 2);
636 M[linkage_segment] + static_offset,
637 M[p->segment] + object_map->static_offset,
638 object_map->static_length * sizeof(uint64_t)
641 // update LOT, ISOT and LOT/ISOT high water
642 lot[p->segment] = packed_pointer(linkage_segment, p->linkage_offset);
643 isot[p->segment] = packed_pointer(linkage_segment, static_offset);
644 stack_header->cur_lot_size = n_segment;
646 // create debug symbol table (optional)
647 struct definition_header *definition_header = (struct definition_header *)(
648 M[p->segment] + object_map->definition_offset
651 int n_debug_symbol0 = n_debug_symbol;
652 char name_buf[DEBUG_NAME_LEN + 1];
655 struct definition *definition = (struct definition *)(
656 (uint64_t *)definition_header + definition_header->def_list_relp
658 *(uint64_t *)definition;
659 definition = (struct definition *)(
660 (uint64_t *)definition_header + definition->forward_relp
663 if (definition->class == CLASS_SEGNAME) {
665 (uint64_t *)definition_header + definition->name_relp,
669 segname_len = strlen(name_buf);
670 name_buf[segname_len] = '$';
672 else if (definition->class == CLASS_TEXT) {
673 rassert(n_debug_symbol < N_DEBUG_SYMBOL);
674 struct debug_symbol *q = debug_symbol + n_debug_symbol++;
675 q->offset = object_map->text_offset + definition->thing_relp;
678 (uint64_t *)definition_header + definition->name_relp,
679 name_buf + segname_len + 1,
680 DEBUG_NAME_LEN - segname_len - 1
682 q->name = strdup(name_buf);
686 p->n_debug_symbol = n_debug_symbol - n_debug_symbol0;
687 p->debug_symbol = debug_symbol + n_debug_symbol0;
692 sizeof(struct debug_symbol),
699 // callback from simulator when fault type 2 occurs
700 void snap_link(void) {
703 "fault type 2 at %06o:%06o accessing %06o:%06o\n",
710 // find segment of faulting instruction (for validation purposes)
711 rassert(cpu.PPR.PSR < n_segment);
712 struct known_segment *p = segment_to_known_segment[cpu.PPR.PSR];
715 // validate link address, using read-only linkage section (safer)
716 struct object_map *object_map = get_object_map(p);
717 struct virgin_linkage_header *virgin_linkage_header =
718 (struct virgin_linkage_header *)(
719 M[p->segment] + object_map->linkage_offset
722 cpu.TPR.TSR == linkage_segment &&
723 (cpu.TPR.CA & 1) == 0 &&
725 p->linkage_offset + virgin_linkage_header->first_ref_relp &&
727 p->linkage_offset + object_map->linkage_length
730 // validate link, using read-only linkage section (safer)
731 int link_relp = (int)(cpu.TPR.CA - p->linkage_offset);
732 struct link *virgin_link = (struct link *)(
733 (uint64_t *)virgin_linkage_header + link_relp
735 rassert(virgin_link->head_ptr == (-link_relp & 0777777));
736 rassert(virgin_link->ft2 == 046);
738 // make sure writeable copy of link hasn't been corrupted
739 struct its_pointer *link = (struct its_pointer *)(
740 M[cpu.TPR.TSR] + cpu.TPR.CA
742 rassert(memcmp(link, virgin_link, sizeof(struct link)) == 0);
744 // look up link target
745 struct definition_header *definition_header = (struct definition_header *)(
746 M[p->segment] + object_map->definition_offset
748 struct exp_word *exp_word = (struct exp_word *)(
749 (uint64_t *)definition_header + virgin_link->exp_ptr
751 struct type_pair *type_pair = (struct type_pair *)(
752 (uint64_t *)definition_header + exp_word->type_relp
754 //rassert(type_pair->trap_relp == 0);
756 type_pair->type >= LINK_SELF_BASE &&
757 type_pair->type <= LINK_CREATE_IF_NOT_FOUND
760 // process link by type
761 char offsetname[NAME_LEN + 1];
763 (uint64_t *)definition_header + type_pair->offsetname_relp,
768 char segname[NAME_LEN + 1];
769 static const int section_to_class[] = {
776 switch (type_pair->type) {
777 case LINK_REFNAME_OFFSETNAME:
778 rassert(type_pair->trap_relp == 0);
780 (uint64_t *)definition_header + type_pair->segname_relp,
784 *link = find_definition(
785 link_segment(NULL, segname, segname),
791 case LINK_SELF_OFFSETNAME:
792 switch (type_pair->segname_relp) {
793 case SECTION_TEXT: // 0
794 case SECTION_LINK: // 1
795 case SECTION_SYMBOL: // 2
796 case SECTION_STATIC: // 4
797 rassert(type_pair->trap_relp == 0);
798 *link = find_definition(
801 section_to_class[type_pair->segname_relp],
807 struct link_init *link_init = (struct link_init *)(
808 (uint64_t *)definition_header + type_pair->trap_relp
810 rassert(link_init->n_words < 01000000);
811 rassert(link_init->type == INIT_NO_INIT);
814 struct system_link *q;
815 for (q = p->system_link_head; q; q = q->next)
816 if (strcmp(q->name, offsetname) == 0) {
817 rassert(q->n_words == (int)link_init->n_words);
818 goto found_system_link;
821 rassert(n_system_link < N_SYSTEM_LINK);
822 q = system_link + n_system_link++;
823 q->n_words = (int)link_init->n_words;
824 q->offset = allocate_linkage((int)link_init->n_words, 2);
825 strcpy(q->name, offsetname);
828 *link = its_pointer(linkage_segment, q->offset);
836 "unimplemented link type %s\n",
837 link_type_names[type_pair->type - 1]
842 link->offset += exp_word->expression;
843 link->modifier1 = virgin_link->modifier;
846 "snap link %06o:%06o -> %s$%s + %06o -> %06o:%06o\n",
849 type_pair->type == LINK_SELF_OFFSETNAME ?
850 symbolic_section_names[type_pair->segname_relp] :
853 (int)exp_word->expression,
859 void emcall_exit_emulation(void) {
860 longjmp(exit_emulation, 1);
863 void emcall_make_entry(void) {
864 struct arg_list *arg_list = (struct arg_list *)(
865 M[cpu.PR[0].SNR] + cpu.PR[0].WORDNO
868 rassert(arg_list->arg_count == 10);
869 struct its_pointer *ref_pointer = (struct its_pointer *)(
870 M[arg_list->args[0].segment] + arg_list->args[0].offset
872 uint64_t *entryname = (uint64_t *)(
873 M[arg_list->args[1].segment] + arg_list->args[1].offset
875 uint64_t *entry_point_name = (uint64_t *)(
876 M[arg_list->args[2].segment] + arg_list->args[2].offset
878 struct based_entry *entry_point = (struct based_entry *)(
879 M[arg_list->args[3].segment] + arg_list->args[3].offset
881 uint64_t *code = (uint64_t *)(
882 M[arg_list->args[4].segment] + arg_list->args[4].offset
885 rassert(arg_list->desc_count == 10);
886 struct arg_desc *entryname_desc = (struct arg_desc *)(
887 M[arg_list->args[6].segment] + arg_list->args[6].offset
889 struct arg_desc *entry_point_name_desc = (struct arg_desc *)(
890 M[arg_list->args[7].segment] + arg_list->args[7].offset
893 char entryname_buf[NAME_LEN + 1];
894 rassert(entryname_desc->size < NAME_LEN + 1);
901 char entry_point_name_buf[NAME_LEN + 1];
902 rassert(entry_point_name_desc->size < NAME_LEN + 1);
904 entry_point_name_buf,
906 entry_point_name_desc->size
909 entry_point->code_ptr =
910 entry_point_name_buf[0] ?
917 entry_point_name_buf,
929 entry_point->env_ptr = its_pointer(-1, 1);
934 "make_entry %s$%s -> %06o:%06o\n",
936 entry_point_name_buf,
937 entry_point->code_ptr.segment,
938 entry_point->code_ptr.offset
942 void emcall_make_ptr(void) {
943 struct arg_list *arg_list = (struct arg_list *)(
944 M[cpu.PR[0].SNR] + cpu.PR[0].WORDNO
947 rassert(arg_list->arg_count == 10);
948 //struct its_pointer *ref_pointer = (struct its_pointer *)(
949 // M[arg_list->args[0].segment] + arg_list->args[0].offset
951 uint64_t *entryname = (uint64_t *)(
952 M[arg_list->args[1].segment] + arg_list->args[1].offset
954 uint64_t *entry_point_name = (uint64_t *)(
955 M[arg_list->args[2].segment] + arg_list->args[2].offset
957 struct its_pointer *entry_point_pointer = (struct its_pointer *)(
958 M[arg_list->args[3].segment] + arg_list->args[3].offset
960 uint64_t *code = (uint64_t *)(
961 M[arg_list->args[4].segment] + arg_list->args[4].offset
964 rassert(arg_list->desc_count == 10);
965 struct arg_desc *entryname_desc = (struct arg_desc *)(
966 M[arg_list->args[6].segment] + arg_list->args[6].offset
968 struct arg_desc *entry_point_name_desc = (struct arg_desc *)(
969 M[arg_list->args[7].segment] + arg_list->args[7].offset
972 char entryname_buf[NAME_LEN + 1];
973 rassert(entryname_desc->size < NAME_LEN + 1);
980 char entry_point_name_buf[NAME_LEN + 1];
981 rassert(entry_point_name_desc->size < NAME_LEN + 1);
983 entry_point_name_buf,
985 entry_point_name_desc->size
988 *entry_point_pointer =
989 entry_point_name_buf[0] ?
996 entry_point_name_buf,
1014 "make_ptr %s$%s -> %06o:%06o\n",
1016 entry_point_name_buf,
1017 entry_point_pointer->segment,
1018 entry_point_pointer->offset
1022 void emcall_make_seg(void) {
1023 struct arg_list *arg_list = (struct arg_list *)(
1024 M[cpu.PR[0].SNR] + cpu.PR[0].WORDNO
1027 rassert(arg_list->arg_count == 12);
1028 uint64_t *dir_name = (uint64_t *)(
1029 M[arg_list->args[0].segment] + arg_list->args[0].offset
1031 uint64_t *entryname = (uint64_t *)(
1032 M[arg_list->args[1].segment] + arg_list->args[1].offset
1034 uint64_t *ref_name = (uint64_t *)(
1035 M[arg_list->args[2].segment] + arg_list->args[2].offset
1037 uint64_t *mode = (uint64_t *)(
1038 M[arg_list->args[3].segment] + arg_list->args[3].offset
1040 struct its_pointer *seg_ptr = (struct its_pointer *)(
1041 M[arg_list->args[4].segment] + arg_list->args[4].offset
1043 uint64_t *code = (uint64_t *)(
1044 M[arg_list->args[5].segment] + arg_list->args[5].offset
1047 rassert(arg_list->desc_count == 12);
1048 struct arg_desc *dir_name_desc = (struct arg_desc *)(
1049 M[arg_list->args[6].segment] + arg_list->args[6].offset
1051 struct arg_desc *entryname_desc = (struct arg_desc *)(
1052 M[arg_list->args[7].segment] + arg_list->args[7].offset
1054 struct arg_desc *ref_name_desc = (struct arg_desc *)(
1055 M[arg_list->args[8].segment] + arg_list->args[8].offset
1058 char dir_name_buf[PATH_LEN];
1059 rassert(dir_name_desc->size < PATH_LEN);
1065 if (dir_name_buf[0] == 0) {
1066 rassert(strlen(multics_process) < PATH_LEN);
1067 strcpy(dir_name_buf, multics_process);
1070 char entryname_buf[NAME_LEN + 1];
1071 rassert(entryname_desc->size < NAME_LEN + 1);
1075 entryname_desc->size
1078 char ref_name_buf[NAME_LEN + 1];
1079 rassert(ref_name_desc->size < NAME_LEN + 1);
1086 // see if already known under this ref_name
1087 struct known_segment *p;
1088 for (int i = 0; i < n_ref_name_to_known_segment; ++i)
1089 if (strcmp(ref_name_to_known_segment[i].ref_name, ref_name_buf) == 0) {
1090 p = ref_name_to_known_segment[i].known_segment;
1096 // allocate table entries
1097 rassert(n_known_segment < N_KNOWN_SEGMENT);
1098 p = known_segment + n_known_segment++;
1100 p->segment = scratch_segment();
1103 "make ref_name %s with segment %06o\n",
1107 segment_to_known_segment[p->segment] = p;
1108 p->writeable = true;
1110 // make known under this ref_name
1111 rassert(n_ref_name_to_known_segment < N_REF_NAME_TO_KNOWN_SEGMENT);
1112 struct ref_name_to_known_segment *q =
1113 ref_name_to_known_segment + n_ref_name_to_known_segment++;
1114 q->ref_name = strdup(ref_name_buf);
1115 rassert(q->ref_name);
1116 q->known_segment = p;
1120 *seg_ptr = its_pointer(p->segment, 0);
1124 "make_seg %s>%s %s -> %06o:%06o\n",
1133 void emcall_proc_info(void) {
1134 fprintf(stderr, "proc_info -> ignored\n");
1137 void emcall_set_ips_mask(void) {
1138 fprintf(stderr, "set_ips_mask -> ignored\n");
1141 void emcall_reset_ips_mask(void) {
1142 fprintf(stderr, "reset_ips_mask -> ignored\n");
1145 void emcall_fs_search_get_wdir(void) {
1146 struct arg_list *arg_list = (struct arg_list *)(
1147 M[cpu.PR[0].SNR] + cpu.PR[0].WORDNO
1150 rassert(arg_list->arg_count == 4);
1151 struct its_pointer *a_pathptr = (struct its_pointer *)(
1152 M[arg_list->args[0].segment] + arg_list->args[0].offset
1154 uint64_t *a_pathcnt = (uint64_t *)(
1155 M[arg_list->args[1].segment] + arg_list->args[1].offset
1158 char path_buf[DNAME_LEN + 1];
1159 int path_len = strlen(multics_home);
1160 rassert(path_len < DNAME_LEN + 1);
1161 strcpy(path_buf, multics_home);
1163 uint64_t *a_path = (uint64_t *)(
1164 M[a_pathptr->segment] + a_pathptr->offset
1166 static const int shifts[] = {27, 18, 9, 0};
1168 for (i = 0; i < path_len; ++i) {
1172 (a_path[j] & ~((uint64_t)0777 << shifts[k])) |
1173 ((uint64_t)path_buf[i] << shifts[k]);
1175 for (; i < DNAME_LEN; ++i) {
1179 (a_path[j] & ~((uint64_t)0777 << shifts[k])) |
1180 ((uint64_t)' ' << shifts[k]);
1182 *a_pathcnt = path_len;
1184 fprintf(stderr, "fs_search_get_wdir -> %s\n", path_buf);
1187 void emcall_initiate_count(void) {
1188 struct arg_list *arg_list = (struct arg_list *)(
1189 M[cpu.PR[0].SNR] + cpu.PR[0].WORDNO
1192 rassert(arg_list->arg_count == 14);
1193 uint64_t *dir_name = (uint64_t *)(
1194 M[arg_list->args[0].segment] + arg_list->args[0].offset
1196 uint64_t *entryname = (uint64_t *)(
1197 M[arg_list->args[1].segment] + arg_list->args[1].offset
1199 uint64_t *ref_name = (uint64_t *)(
1200 M[arg_list->args[2].segment] + arg_list->args[2].offset
1202 uint64_t *bit_count = (uint64_t *)(
1203 M[arg_list->args[3].segment] + arg_list->args[3].offset
1205 //uint64_t *copy_ctl_sw = (uint64_t *)(
1206 // M[arg_list->args[4].segment] + arg_list->args[4].offset
1208 struct its_pointer *seg_ptr = (struct its_pointer *)(
1209 M[arg_list->args[5].segment] + arg_list->args[5].offset
1211 uint64_t *code = (uint64_t *)(
1212 M[arg_list->args[6].segment] + arg_list->args[6].offset
1215 rassert(arg_list->desc_count == 14);
1216 struct arg_desc *dir_name_desc = (struct arg_desc *)(
1217 M[arg_list->args[7].segment] + arg_list->args[7].offset
1219 struct arg_desc *entryname_desc = (struct arg_desc *)(
1220 M[arg_list->args[8].segment] + arg_list->args[8].offset
1222 struct arg_desc *ref_name_desc = (struct arg_desc *)(
1223 M[arg_list->args[9].segment] + arg_list->args[9].offset
1226 char dir_name_buf[PATH_LEN];
1227 rassert(dir_name_desc->size < PATH_LEN);
1234 char entryname_buf[NAME_LEN + 1];
1235 rassert(entryname_desc->size < NAME_LEN + 1);
1239 entryname_desc->size
1242 char ref_name_buf[NAME_LEN + 1];
1243 rassert(ref_name_desc->size < NAME_LEN + 1);
1251 struct known_segment *p = initiate_segment(
1258 *bit_count = p->bitcount;
1259 *seg_ptr = its_pointer(p->segment, 0);
1260 *code = already ? *segknown : 0;
1264 "initiate_count %s>%s %s -> %06o:%06o\n",
1273 void emcall_fs_get_mode(void) {
1274 struct arg_list *arg_list = (struct arg_list *)(
1275 M[cpu.PR[0].SNR] + cpu.PR[0].WORDNO
1278 rassert(arg_list->arg_count == 6);
1279 struct its_pointer *seg_ptr = (struct its_pointer *)(
1280 M[arg_list->args[0].segment] + arg_list->args[0].offset
1282 uint64_t *mode = (uint64_t *)(
1283 M[arg_list->args[1].segment] + arg_list->args[1].offset
1285 uint64_t *code = (uint64_t *)(
1286 M[arg_list->args[2].segment] + arg_list->args[2].offset
1289 rassert(seg_ptr->segment < n_segment);
1290 struct known_segment *p = segment_to_known_segment[seg_ptr->segment];
1293 *mode = p->writeable ? RW_ACCESS_BIN : R_ACCESS_BIN;
1298 "fs_get_mode %06o:%06o -> %lo\n",
1305 void emcall_high_low_seg_count(void) {
1306 struct arg_list *arg_list = (struct arg_list *)(
1307 M[cpu.PR[0].SNR] + cpu.PR[0].WORDNO
1310 rassert(arg_list->arg_count == 4);
1311 uint64_t *nonhardcore_seg_count = (uint64_t *)(
1312 M[arg_list->args[0].segment] + arg_list->args[0].offset
1314 uint64_t *lowest_nonhardcore_segno = (uint64_t *)(
1315 M[arg_list->args[1].segment] + arg_list->args[1].offset
1318 *nonhardcore_seg_count = n_segment;
1319 *lowest_nonhardcore_segno = 1;
1323 "emcall_high_low_seg_count returns %012lo, %012lo\n",
1324 *nonhardcore_seg_count,
1325 *lowest_nonhardcore_segno
1330 void emcall_get_line(void) {
1331 struct arg_list *arg_list = (struct arg_list *)(
1332 M[cpu.PR[0].SNR] + cpu.PR[0].WORDNO
1335 rassert(arg_list->arg_count == 10);
1336 struct its_pointer *iocb_ptr = (struct its_pointer *)(
1337 M[arg_list->args[0].segment] + arg_list->args[0].offset
1339 struct its_pointer *buff_ptr = (struct its_pointer *)(
1340 M[arg_list->args[1].segment] + arg_list->args[1].offset
1342 uint64_t *buff_len = (uint64_t *)(
1343 M[arg_list->args[2].segment] + arg_list->args[2].offset
1345 uint64_t *n_read = (uint64_t *)(
1346 M[arg_list->args[3].segment] + arg_list->args[3].offset
1348 uint64_t *code = (uint64_t *)(
1349 M[arg_list->args[4].segment] + arg_list->args[4].offset
1354 iocb_ptr->segment == user_input->segment &&
1355 iocb_ptr->offset == user_input->offset
1361 fprintf(stderr, "emcall_get_line %ld\n", *buff_len);
1364 uint64_t *buff = (uint64_t *)(M[buff_ptr->segment] + buff_ptr->offset);
1365 static const int shifts[] = {27, 18, 9, 0};
1366 while (*n_read < *buff_len) {
1369 *code = *n_read ? *short_record : *end_of_info;
1370 fprintf(stderr, "emcall_get_line returns %ld, %012lo\n", *n_read, *code);
1373 size_t i = (size_t)(*n_read >> 2);
1374 int j = (int)(*n_read & 3);
1377 (buff[i] & ~((uint64_t)0777 << shifts[j])) |
1378 ((uint64_t)c << shifts[j]);
1381 fprintf(stderr, "emcall_get_line returns %ld, %012lo\n", *n_read, *code);
1385 *code = *long_record;
1386 fprintf(stderr, "emcall_get_line returns %ld, %012lo\n", *n_read, *code);
1389 void emcall_put_chars(void) {
1390 struct arg_list *arg_list = (struct arg_list *)(
1391 M[cpu.PR[0].SNR] + cpu.PR[0].WORDNO
1394 rassert(arg_list->arg_count == 8);
1395 struct its_pointer *iocb_ptr = (struct its_pointer *)(
1396 M[arg_list->args[0].segment] + arg_list->args[0].offset
1398 struct its_pointer *buff_ptr = (struct its_pointer *)(
1399 M[arg_list->args[1].segment] + arg_list->args[1].offset
1401 uint64_t *n = (uint64_t *)(
1402 M[arg_list->args[2].segment] + arg_list->args[2].offset
1404 uint64_t *code = (uint64_t *)(
1405 M[arg_list->args[3].segment] + arg_list->args[3].offset
1410 iocb_ptr->segment == user_output->segment &&
1411 iocb_ptr->offset == user_output->offset
1415 iocb_ptr->segment == error_output->segment &&
1416 iocb_ptr->offset == error_output->offset
1422 fprintf(stderr, "emcall_put_chars %ld\n", *n);
1424 uint64_t *buff = (uint64_t *)(M[buff_ptr->segment] + buff_ptr->offset);
1425 static const int shifts[] = {27, 18, 9, 0};
1426 for (uint64_t i = 0; i < *n; ++i)
1427 fputc((char)(buff[i >> 2] >> shifts[i & 3]), fp);
1433 int main(int argc, char **argv) {
1435 if (argc >= 2 && strcmp(argv[1], "--af") == 0) {
1437 memmove(argv + 1, argv + 2, (argc - 2) * sizeof(char **));
1442 "usage: %s [--af] entry_segname$entry_name [arguments]\n",
1447 char *entry_segname, *entry_name;
1449 char *p = strchr(argv[1], '$');
1452 entry_segname = argv[1];
1455 int n_args = argc - 2;
1456 char **args = argv + 2;
1490 cpu_reset_unit_idx(0, false);
1491 set_addr_mode(APPEND_mode);
1493 // initialize memory
1494 uint64_t *null_segment = mmap(
1496 01000000 * sizeof(uint64_t),
1498 MAP_ANONYMOUS | MAP_PRIVATE,
1502 rassert(null_segment != (uint64_t *)-1);
1503 for (int i = 0; i < 0100000; ++i)
1504 M[i] = (word36 *)null_segment;
1507 // create linkage segment
1508 linkage_segment = scratch_segment();
1509 //next_linkage_offset = 0;
1511 // create stack segment
1512 stack_segment = scratch_segment();
1513 next_stack_offset = sizeof(struct stack_header) / sizeof(uint64_t);
1514 stack_header = (struct stack_header *)M[stack_segment];
1515 stack_header->null_ptr = its_pointer(-1, 1);
1516 stack_header->ect_ptr = its_pointer(-1, 1);
1517 stack_header->heap_header_ptr = its_pointer(-1, 1);
1518 stack_header->sys_link_info_ptr = its_pointer(-1, 1);
1520 // allocate LOT and ISOT
1521 stack_header->max_lot_size = N_SEGMENT;
1522 int lot_offset = allocate_linkage(N_SEGMENT, 1);
1523 lot = (struct packed_pointer *)(M[linkage_segment] + lot_offset);
1524 stack_header->lot_ptr = its_pointer(linkage_segment, lot_offset);
1525 int isot_offset = allocate_linkage(N_SEGMENT, 1);
1526 isot = (struct packed_pointer *)(M[linkage_segment] + isot_offset);
1527 stack_header->isot_ptr = its_pointer(linkage_segment, isot_offset);
1528 int sct_offset = allocate_linkage(0, 1); // ???
1529 //sct = (struct packed_pointer *)(M[linkage_segment] + sct_offset);
1530 stack_header->sct_ptr = its_pointer(linkage_segment, sct_offset);
1532 // load pl1 operators
1533 stack_header->signal_ptr = find_definition(
1534 link_segment(NULL, "signal_", "signal_"),
1539 stack_header->unwinder_ptr = find_definition(
1540 link_segment(NULL, "unwinder_", "unwinder_"),
1545 stack_header->trans_op_tv_ptr = find_definition(
1546 link_segment(NULL, "operator_pointers_", "operator_pointers_"),
1547 "operator_pointers_",
1552 struct known_segment *p =
1553 link_segment(NULL, "pl1_operators_", "pl1_operators_");
1554 struct its_pointer operator_table_pointer = find_definition(
1560 stack_header->pl1_operators_ptr = operator_table_pointer;
1561 stack_header->call_op_ptr = find_definition(
1567 stack_header->push_op_ptr = find_definition(
1573 stack_header->return_op_ptr = find_definition(
1579 stack_header->no_pop_op_ptr = find_definition(
1581 "alm_return_no_pop",
1585 stack_header->entry_op_ptr = find_definition(
1592 // optional: extra debugging symbols
1593 int begin_pl1_operators_offset = find_definition(
1595 "begin_pl1_operators",
1599 rassert(n_debug_symbol + N_DEBUG_SYMBOL_PL1_OPERATORS <= N_DEBUG_SYMBOL);
1601 debug_symbol + n_debug_symbol,
1602 debug_symbol_pl1_operators,
1603 sizeof(debug_symbol_pl1_operators)
1605 for (int i = 0; i < N_DEBUG_SYMBOL_PL1_OPERATORS; ++i)
1606 debug_symbol[n_debug_symbol + i].offset += begin_pl1_operators_offset;
1607 n_debug_symbol += N_DEBUG_SYMBOL_PL1_OPERATORS;
1608 p->n_debug_symbol += N_DEBUG_SYMBOL_PL1_OPERATORS;
1612 sizeof(struct debug_symbol),
1613 compare_debug_symbol
1616 // initiate iox_ segment for emcall use
1617 struct known_segment *iox =
1618 link_segment(NULL, "iox_", "iox_");
1619 struct its_pointer user_input_pointer = find_definition(
1625 user_input = (struct its_pointer *)(
1626 M[user_input_pointer.segment] + user_input_pointer.offset
1628 struct its_pointer user_output_pointer = find_definition(
1634 user_output = (struct its_pointer *)(
1635 M[user_output_pointer.segment] + user_output_pointer.offset
1637 struct its_pointer error_output_pointer = find_definition(
1643 error_output = (struct its_pointer *)(
1644 M[error_output_pointer.segment] + error_output_pointer.offset
1647 // initiate error_table segment for emcall use
1648 struct known_segment *error_table =
1649 link_segment(NULL, "error_table_", "error_table_");
1650 struct its_pointer end_of_info_pointer = find_definition(
1656 end_of_info = (uint64_t *)(
1657 M[end_of_info_pointer.segment] + end_of_info_pointer.offset
1659 struct its_pointer long_record_pointer = find_definition(
1665 long_record = (uint64_t *)(
1666 M[long_record_pointer.segment] + long_record_pointer.offset
1668 struct its_pointer segknown_pointer = find_definition(
1674 segknown = (uint64_t *)(
1675 M[segknown_pointer.segment] + segknown_pointer.offset
1677 struct its_pointer short_record_pointer = find_definition(
1683 short_record = (uint64_t *)(
1684 M[short_record_pointer.segment] + short_record_pointer.offset
1687 // create first stack frame
1688 int stack_frame_offset = allocate_stack(
1689 sizeof(struct stack_frame) / sizeof(uint64_t),
1692 struct stack_frame *stack_frame = (struct stack_frame *)(
1693 M[stack_segment] + stack_frame_offset
1695 stack_header->stack_begin_ptr = its_pointer(
1700 // create argument list, will be reused several times with different
1701 // sizes during initialization, also is a marker for resetting stack
1702 int arg_list_offset = allocate_stack(0, 2);
1703 struct arg_list *arg_list = (struct arg_list *)(
1704 M[stack_segment] + arg_list_offset
1707 // create emcall stubs
1708 emcall_stubs_offset = allocate_linkage(37, 1);
1709 uint64_t *emcall_stubs = (uint64_t *)(
1710 M[linkage_segment] + emcall_stubs_offset
1713 emcall_stubs[0] = 0700046272120L; // tsp2 pr7|46,n* alm_entry
1714 emcall_stubs[1] = 0000001420400L; // emcall make_entry
1715 emcall_stubs[2] = 0700044710120L; // tra pr7|44,n* alm_return_no_pop
1717 emcall_stubs[3] = 0700046272120L; // tsp2 pr7|46,n* alm_entry
1718 emcall_stubs[4] = 0000002420400L; // emcall make_ptr
1719 emcall_stubs[5] = 0700044710120L; // tra pr7|44,n* alm_return_no_pop
1721 emcall_stubs[6] = 0700046272120L; // tsp2 pr7|46,n* alm_entry
1722 emcall_stubs[7] = 0000003420400L; // emcall make_seg
1723 emcall_stubs[8] = 0700044710120L; // tra pr7|44,n* alm_return_no_pop
1725 emcall_stubs[9] = 0700046272120L; // tsp2 pr7|46,n* alm_entry
1726 emcall_stubs[10] = 0000004420400L; // emcall proc_info
1727 emcall_stubs[11] = 0700044710120L; // tra pr7|44,n* alm_return_no_pop
1729 emcall_stubs[12] = 0700046272120L; // tsp2 pr7|46,n* alm_entry
1730 emcall_stubs[13] = 0000005420400L; // emcall set_ips_mask
1731 emcall_stubs[14] = 0700044710120L; // tra pr7|44,n* alm_return_no_pop
1733 emcall_stubs[15] = 0700046272120L; // tsp2 pr7|46,n* alm_entry
1734 emcall_stubs[16] = 0000006420400L; // emcall reset_ips_mask
1735 emcall_stubs[17] = 0700044710120L; // tra pr7|44,n* alm_return_no_pop
1737 emcall_stubs[18] = 0700046272120L; // tsp2 pr7|46,n* alm_entry
1738 emcall_stubs[19] = 0000007420400L; // emcall fs_search_get_wdir
1739 emcall_stubs[20] = 0700044710120L; // tra pr7|44,n* alm_return_no_pop
1741 emcall_stubs[21] = 0700046272120L; // tsp2 pr7|46,n* alm_entry
1742 emcall_stubs[22] = 0000010420400L; // emcall initiate_count
1743 emcall_stubs[23] = 0700044710120L; // tra pr7|44,n* alm_return_no_pop
1745 emcall_stubs[24] = 0700046272120L; // tsp2 pr7|46,n* alm_entry
1746 emcall_stubs[25] = 0000011420400L; // emcall fs_get_mode
1747 emcall_stubs[26] = 0700044710120L; // tra pr7|44,n* alm_return_no_pop
1749 emcall_stubs[27] = 0700046272120L; // tsp2 pr7|46,n* alm_entry
1750 emcall_stubs[28] = 0000012420400L; // emcall high_low_seg_count
1751 emcall_stubs[29] = 0700044710120L; // tra pr7|44,n* alm_return_no_pop
1753 emcall_stubs[30] = 0700046272120L; // tsp2 pr7|46,n* alm_entry
1754 emcall_stubs[31] = 0000013420400L; // emcall get_line
1755 emcall_stubs[32] = 0700044710120L; // tra pr7|44,n* alm_return_no_pop
1757 emcall_stubs[33] = 0700046272120L; // tsp2 pr7|46,n* alm_entry
1758 emcall_stubs[34] = 0000014420400L; // emcall put_chars
1759 emcall_stubs[35] = 0700044710120L; // tra pr7|44,n* alm_return_no_pop
1761 emcall_stubs[36] = 0400000000000L; // bit(1) indicating system is up
1763 // create calling stub
1764 int calling_stub_offset = allocate_linkage(2, 1);
1765 uint64_t *calling_stub = (uint64_t *)(
1766 M[linkage_segment] + calling_stub_offset
1768 stack_frame->return_ptr = its_pointer(
1770 0 // will be overwritten by call_ext_out
1772 calling_stub[0] = 0000622700100L; // tsx0 pr0|402 call_ext_out_desc
1773 calling_stub[1] = 0000000420400L; // emcall exit_emulation
1775 // initialize area allocator
1776 fprintf(stderr, "call bound_library_1_$define_area_\n");
1778 next_stack_offset = arg_list_offset;
1779 allocate_stack(sizeof(struct arg_list) / sizeof(uint64_t) + 4, 2);
1781 int area_info_pointer_offset = allocate_stack(2, 2);
1782 arg_list->args[0] = its_pointer(stack_segment, area_info_pointer_offset);
1784 struct its_pointer *area_info_pointer = (struct its_pointer *)(
1785 M[stack_segment] + area_info_pointer_offset
1787 int area_info_offset = allocate_stack(
1788 sizeof(struct area_info) / sizeof(uint64_t),
1791 *area_info_pointer = its_pointer(stack_segment, area_info_offset);
1793 struct area_info *area_info = (struct area_info *)(
1794 M[stack_segment] + area_info_offset
1796 area_info->size = 0100000; // smaller than sys_info$max_seg_size
1797 area_info->areap = its_pointer(-1, 1);
1798 area_info->version = 1;
1799 memset(&area_info->control, 0, sizeof(area_info->control));
1800 area_info->control.extend = 1;
1801 area_info->control.zero_on_free = 1;
1802 area_info->control.system = 1;
1803 area_info->owner[0] = 0154151156153; // 'link'
1804 area_info->owner[1] = 0145162040040; // 'er '
1805 area_info->owner[2] = 0040040040040; // ' '
1806 area_info->owner[3] = 0040040040040; // ' '
1807 area_info->owner[4] = 0040040040040; // ' '
1808 area_info->owner[5] = 0040040040040; // ' '
1809 area_info->owner[6] = 0040040040040; // ' '
1810 area_info->owner[7] = 0040040040040; // ' '
1812 int code_offset = allocate_stack(1, 1);
1813 arg_list->args[1] = its_pointer(stack_segment, code_offset);
1815 stack_header->stack_end_ptr = its_pointer(
1817 allocate_stack(0, 0x10)
1821 cpu.rX[1] = arg_list_offset;
1824 cpu.PR[0].SNR = operator_table_pointer.segment;
1825 cpu.PR[0].WORDNO = operator_table_pointer.offset;
1827 struct its_pointer define_area_pointer = find_definition(
1828 link_segment(NULL, "bound_library_1_", "bound_library_1_"),
1834 cpu.PR[2].SNR = define_area_pointer.segment;
1835 cpu.PR[2].WORDNO = define_area_pointer.offset;
1838 cpu.PR[6].SNR = stack_segment;
1839 cpu.PR[6].WORDNO = stack_frame_offset;
1842 cpu.PPR.PSR = linkage_segment;
1843 cpu.PPR.P = 0; // privilege
1844 cpu.PPR.IC = calling_stub_offset;
1846 cpu.cycle = FETCH_cycle;
1848 if (setjmp(exit_emulation) == 0) {
1853 rassert(M[stack_segment][code_offset] == 0);
1854 stack_header->system_free_ptr = area_info->areap;
1855 stack_header->user_free_ptr = area_info->areap;
1856 stack_header->system_free_ptr = area_info->areap;
1857 stack_header->assign_linkage_ptr = area_info->areap;
1858 stack_header->clr_ptr = area_info->areap;
1860 // attach standard IOCBs
1861 // (they will not work -- but try to avoid crashes if accessed)
1862 fprintf(stderr, "call iox_$init_standard_iocbs\n");
1864 next_stack_offset = arg_list_offset;
1865 allocate_stack(sizeof(struct arg_list) / sizeof(uint64_t), 2);
1867 stack_header->stack_end_ptr = its_pointer(
1869 allocate_stack(0, 0x10)
1873 cpu.rX[1] = arg_list_offset;
1876 cpu.PR[0].SNR = operator_table_pointer.segment;
1877 cpu.PR[0].WORDNO = operator_table_pointer.offset;
1879 struct its_pointer init_standard_iocbs_pointer = find_definition(
1881 "init_standard_iocbs",
1886 cpu.PR[2].SNR = init_standard_iocbs_pointer.segment;
1887 cpu.PR[2].WORDNO = init_standard_iocbs_pointer.offset;
1890 cpu.PR[6].SNR = stack_segment;
1891 cpu.PR[6].WORDNO = stack_frame_offset;
1894 cpu.PPR.PSR = linkage_segment;
1895 cpu.PPR.P = 0; // privilege
1896 cpu.PPR.IC = calling_stub_offset;
1898 cpu.cycle = FETCH_cycle;
1900 if (setjmp(exit_emulation) == 0) {
1905 #if 0 // opening does not work, gives a "not attached" error
1906 // open standard IOCBs
1907 fprintf(stderr, "call iox_$open\n");
1909 next_stack_offset = arg_list_offset;
1910 allocate_stack(sizeof(struct arg_list) / sizeof(uint64_t) + 8, 2);
1912 arg_list->args[0] = find_definition(
1919 int mode_offset = allocate_stack(1, 1);
1920 arg_list->args[1] = its_pointer(stack_segment, mode_offset);
1921 M[stack_segment][mode_offset] = STREAM_INPUT_OUTPUT;
1923 int unused_offset = allocate_stack(1, 1);
1924 arg_list->args[2] = its_pointer(stack_segment, unused_offset);
1925 M[stack_segment][unused_offset] = 0;
1927 /*int*/ code_offset = allocate_stack(1, 1);
1928 arg_list->args[3] = its_pointer(stack_segment, code_offset);
1930 stack_header->stack_end_ptr = its_pointer(
1932 allocate_stack(0, 0x10)
1936 cpu.rX[1] = arg_list_offset;
1939 cpu.PR[0].SNR = operator_table_pointer.segment;
1940 cpu.PR[0].WORDNO = operator_table_pointer.offset;
1942 struct its_pointer open_pointer = find_definition(
1949 cpu.PR[2].SNR = open_pointer.segment;
1950 cpu.PR[2].WORDNO = open_pointer.offset;
1953 cpu.PR[6].SNR = stack_segment;
1954 cpu.PR[6].WORDNO = stack_frame_offset;
1957 cpu.PPR.PSR = linkage_segment;
1958 cpu.PPR.P = 0; // privilege
1959 cpu.PPR.IC = calling_stub_offset;
1961 cpu.cycle = FETCH_cycle;
1963 if (setjmp(exit_emulation) == 0) {
1968 rassert(M[stack_segment][code_offset] == 0);
1971 // call requested entry
1972 fprintf(stderr, "call %s$%s\n", entry_segname, entry_name);
1974 int n_args_af = n_args + af;
1975 next_stack_offset = arg_list_offset;
1977 sizeof(struct arg_list) / sizeof(uint64_t) + n_args_af * 4,
1981 for (int i = 0; i < n_args; ++i) {
1982 int arg_len = strlen(args[i]);
1983 int arg_offset = allocate_stack((arg_len + 3) >> 2, 1);
1984 arg_list->args[i] = its_pointer(stack_segment, arg_offset);
1986 uint64_t *arg = (uint64_t *)(M[stack_segment] + arg_offset);
1987 static int shifts[4] = {27, 18, 9, 0};
1988 for (int j = 0; j < arg_len; ++j) {
1992 (arg[k] & ~((uint64_t)0777 << shifts[l])) |
1993 ((uint64_t)args[i][j] << shifts[l]);
1996 int arg_desc_offset = allocate_stack(
1997 sizeof(struct arg_desc) / sizeof(uint64_t),
2000 arg_list->args[n_args_af + i] =
2001 its_pointer(stack_segment, arg_desc_offset);
2003 struct arg_desc *arg_desc = (struct arg_desc *)(
2004 M[stack_segment] + arg_desc_offset
2006 arg_desc->flag = 1; // version 2 descriptor
2007 arg_desc->type = 21; // character string
2008 arg_desc->packed = 0;
2009 arg_desc->number_dims = 0;
2010 arg_desc->size = strlen(args[i]);
2013 int result_offset = 0; // shuts up compiler
2015 result_offset = allocate_stack(((RESULT_LEN + 3) >> 2) + 1, 1);
2016 arg_list->args[n_args] = its_pointer(stack_segment, result_offset + 1);
2018 int arg_desc_offset = allocate_stack(
2019 sizeof(struct arg_desc) / sizeof(uint64_t),
2022 arg_list->args[n_args_af + n_args] =
2023 its_pointer(stack_segment, arg_desc_offset);
2025 struct arg_desc *arg_desc = (struct arg_desc *)(
2026 M[stack_segment] + arg_desc_offset
2028 arg_desc->flag = 1; // version 2 descriptor
2029 arg_desc->type = 22; // varying character string
2030 arg_desc->packed = 0;
2031 arg_desc->number_dims = 0;
2032 arg_desc->size = RESULT_LEN;
2035 stack_header->stack_end_ptr = its_pointer(
2037 allocate_stack(0, 0x10)
2040 cpu.rA = n_args_af << 19;
2041 cpu.rX[1] = arg_list_offset;
2044 cpu.PR[0].SNR = operator_table_pointer.segment;
2045 cpu.PR[0].WORDNO = operator_table_pointer.offset;
2047 struct its_pointer entry_pointer = find_definition(
2048 link_segment(NULL, entry_segname, entry_segname),
2054 cpu.PR[2].SNR = entry_pointer.segment;
2055 cpu.PR[2].WORDNO = entry_pointer.offset;
2058 cpu.PR[6].SNR = stack_segment;
2059 cpu.PR[6].WORDNO = stack_frame_offset;
2062 cpu.PPR.PSR = linkage_segment;
2063 cpu.PPR.P = 0; // privilege
2064 cpu.PPR.IC = calling_stub_offset;
2066 cpu.cycle = FETCH_cycle;
2068 if (setjmp(exit_emulation) == 0) {
2074 char buf[RESULT_LEN + 1];
2075 uint64_t *result = (uint64_t *)(M[stack_segment] + result_offset);
2076 int result_len = (int)(*result++ & 0777777);
2077 rassert(result_len < sizeof(buf));
2078 get_string(buf, result, result_len);
2079 printf("%s\n", buf);