Implement hcs_$make_ptr()
authorNick Downing <nick@ndcode.org>
Thu, 24 Oct 2019 13:37:08 +0000 (00:37 +1100)
committerNick Downing <nick@ndcode.org>
Thu, 24 Oct 2019 13:37:08 +0000 (00:37 +1100)
dps8/dps8_ins.c
multics_sim.c

index afd1516..209bca7 100644 (file)
@@ -9683,10 +9683,19 @@ static int emCall (void)
 
         // case 21 defined above
 
- case 22:
-  ;
-  extern jmp_buf exit_emulation;
-  longjmp(exit_emulation, 1);
+ case 026:
+  {
+   void emcall_exit_emulation(void);
+   emcall_exit_emulation();
+  }
+  break;
+ case 027:
+  {
+   void emcall_make_ptr(void);
+   emcall_make_ptr();
+  }
+  break;
+
     }
     return 0;
 }
index ba1f915..1300f0b 100644 (file)
@@ -67,21 +67,22 @@ struct system_link {
 } system_link[N_SYSTEM_LINK];
 
 #define N_LOADED_SEGMENT 0x100
-int n_loaded_segment;
-struct loaded_segment {
+int n_known_segment;
+struct known_segment {
   const char *name;
   int segment;
   int bitcount;
   int linkage_offset;
   struct system_link *system_link_head;
-} loaded_segment[N_LOADED_SEGMENT];
+} known_segment[N_LOADED_SEGMENT];
 
 #define N_SEGMENT 0x200
-struct loaded_segment *loaded_segment_xref[N_SEGMENT];
+struct known_segment *known_segment_xref[N_SEGMENT];
 int next_segment;
 
 int linkage_segment;
 int next_linkage_offset;
+int emcall_stubs_offset;
 struct packed_pointer *lot;
 struct packed_pointer *isot;
 
@@ -112,7 +113,7 @@ int scratch_segment(void) {
   return segment;
 }
 
-struct object_map *get_object_map(struct loaded_segment *p) {
+struct object_map *get_object_map(struct known_segment *p) {
   rassert(p->bitcount % 36 == 0);
   int wordcount = (p->bitcount / 36) & 0777777;
   rassert(wordcount >= 1);
@@ -146,7 +147,7 @@ int allocate_stack(int length, int align) {
   return offset;
 }
 
-const char *xlate_segment(const char *name) {
+const char *xlate_segname(const char *name) {
   // search for segment in path
   int path_index;
   for (path_index = 0; path_index < N_PATHS; ++path_index) {
@@ -182,22 +183,24 @@ const char *xlate_segment(const char *name) {
   return name;
 }
 
-struct loaded_segment *load_segment(const char *name) {
+struct known_segment *make_known(const char *name) {
+  name = xlate_segname(name);
   // see if already loaded
-  for (int i = 0; i < n_loaded_segment; ++i)
-    if (strcmp(loaded_segment[i].name, name) == 0)
-      return loaded_segment + i;
+  for (int i = 0; i < n_known_segment; ++i)
+    if (strcmp(known_segment[i].name, name) == 0)
+      return known_segment + i;
 
   // allocate table entries
-  rassert(n_loaded_segment < N_LOADED_SEGMENT);
-  struct loaded_segment *p =
-    loaded_segment + n_loaded_segment++;
+  rassert(n_known_segment < N_LOADED_SEGMENT);
+  struct known_segment *p =
+    known_segment + n_known_segment++;
   p->name = strdup(name);
   rassert(p->name);
 
   p->segment = allocate_segment();
   fprintf(stderr, "load segname %s into segment %06o\n", name, p->segment);
-  loaded_segment_xref[p->segment] = p;
+  known_segment_xref[p->segment] = p;
 
   // search for segment in path
   int path_index;
@@ -256,72 +259,79 @@ found_segment:
   exit(EXIT_FAILURE);
 
 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
+  p->linkage_offset = 0;
+  p->system_link_head = NULL;
+  return p;
+}
+
+struct known_segment *link_segment(const char *name) {
+  struct known_segment *p = make_known(name);
+
+  if (p->linkage_offset == 0) {
+    // validate linkage header
+    struct object_map *object_map = get_object_map(p);
+    rassert(
+      object_map->linkage_length >=
+        sizeof(struct linkage_header) / sizeof(uint64_t)
     );
-  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);
+    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(
+    // 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,
+      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,
+      virgin_linkage_header,
+      object_map->linkage_length * sizeof(uint64_t)
+    );
+    linkage_header->def_ptr = its_pointer(
+      p->segment,
+      object_map->definition_offset
+    );
+    linkage_header->symbol_ptr = packed_pointer(
+      p->segment,
+      object_map->symbol_offset
+    );
+    linkage_header->original_linkage_ptr = packed_pointer(
+      p->segment,
+      object_map->linkage_offset
+    );
+    linkage_header->stats_segment_number = linkage_segment;
+
+    // copy static section
+    int static_offset = allocate_linkage(object_map->static_length, 2);
+    memcpy(
+      M[linkage_segment] + static_offset,
+      M[p->segment] + object_map->static_offset,
+      object_map->static_length * sizeof(uint64_t)
     );
-  struct linkage_header *linkage_header = (struct linkage_header *)(
-    M[linkage_segment] + p->linkage_offset
-  );
-  memcpy(
-    linkage_header,
-    virgin_linkage_header,
-    object_map->linkage_length * sizeof(uint64_t)
-  );
-  linkage_header->def_ptr = its_pointer(
-    p->segment,
-    object_map->definition_offset
-  );
-  linkage_header->symbol_ptr = packed_pointer(
-    p->segment,
-    object_map->symbol_offset
-  );
-  linkage_header->original_linkage_ptr = packed_pointer(
-    p->segment,
-    object_map->linkage_offset
-  );
-  linkage_header->stats_segment_number = linkage_segment;
-
-  // copy static section
-  int static_offset = allocate_linkage(object_map->static_length, 2);
-  memcpy(
-    M[linkage_segment] + static_offset,
-    M[p->segment] + object_map->static_offset,
-    object_map->static_length * sizeof(uint64_t)
-  );
-
-  // update LOT, ISOT and LOT/ISOT high water
-  lot[p->segment] = packed_pointer(linkage_segment, p->linkage_offset);
-  isot[p->segment] = packed_pointer(linkage_segment, static_offset);
-  stack_header->cur_lot_size = next_segment;
 
-  p->system_link_head = NULL;
+    // update LOT, ISOT and LOT/ISOT high water
+    lot[p->segment] = packed_pointer(linkage_segment, p->linkage_offset);
+    isot[p->segment] = packed_pointer(linkage_segment, static_offset);
+    stack_header->cur_lot_size = next_segment;
+  }
   return p;
 }
 
@@ -335,12 +345,34 @@ void get_acc_string(uint64_t *acc_string, char *buf, int buf_len) {
   buf[len] = 0;
 }
 
+void get_string(char *buf, const uint64_t *string, int string_len) {
+  static int shifts[4] = {27, 18, 9, 0};
+  for (int i = 0; i < string_len; ++i)
+    buf[i] = (char)(string[i >> 2] >> shifts[i & 3]);
+  buf[string_len] = 0;
+}
+
+void get_string_rstrip(char *buf, const uint64_t *string, int string_len) {
+  static int shifts[4] = {27, 18, 9, 0};
+  for (int i = 0; i < string_len; ++i)
+    buf[i] = (char)(string[i >> 2] >> shifts[i & 3]);
+  while (string_len && buf[string_len - 1] == ' ')
+    --string_len;
+  buf[string_len] = 0;
+}
+
 struct its_pointer find_definition(
-  struct loaded_segment *p,
+  struct known_segment *p,
   const char *name,
   int class,
   bool entry
 ) {
+  // redirect specific entry points to emcall stubs
+  if (strcmp(p->name, "hcs_") == 0) {
+    if (strcmp(name, "make_ptr") == 0)
+      return its_pointer(linkage_segment, emcall_stubs_offset);
+  }
+
   struct object_map *object_map = get_object_map(p);
   struct definition_header *definition_header = (struct definition_header *)(
     M[p->segment] + object_map->definition_offset
@@ -416,7 +448,7 @@ void snap_link(void) {
 
   // find segment of faulting instruction (for validation purposes)
   rassert(cpu.PPR.PSR < N_SEGMENT);
-  struct loaded_segment *p = loaded_segment_xref[cpu.PPR.PSR];
+  struct known_segment *p = known_segment_xref[cpu.PPR.PSR];
   rassert(p);
 
   // validate link address, using read-only linkage section (safer)
@@ -489,7 +521,7 @@ void snap_link(void) {
       sizeof(segname)
     );
     *link = find_definition(
-      load_segment(xlate_segment(segname)),
+      link_segment(segname),
       offsetname,
       -1,
       false
@@ -563,6 +595,61 @@ void snap_link(void) {
   );
 }
 
+void emcall_exit_emulation(void) {
+  longjmp(exit_emulation, 1);
+}
+
+void emcall_make_ptr(void) {
+  struct arg_list *arg_list = (struct arg_list *)(
+    M[stack_segment] + cpu.rX[1]
+  );
+
+  rassert(arg_list->arg_count == 10);
+  struct its_pointer *ref_pointer = (struct its_pointer *)(
+    M[arg_list->args[0].segment] + arg_list->args[0].address
+  );
+  uint64_t *entryname = (uint64_t *)(
+    M[arg_list->args[1].segment] + arg_list->args[1].address
+  );
+  uint64_t *entry_point_name = (uint64_t *)(
+    M[arg_list->args[2].segment] + arg_list->args[2].address
+  );
+  struct its_pointer *entry_point_pointer = (struct its_pointer *)(
+    M[arg_list->args[3].segment] + arg_list->args[3].address
+  );
+  uint64_t *code = (uint64_t *)(
+    M[arg_list->args[4].segment] + arg_list->args[4].address
+  );
+
+  char entryname_buf[NAME_LEN + 1];
+  get_string_rstrip(entryname_buf, entryname, NAME_LEN);
+
+  char entry_point_name_buf[NAME_LEN + 1];
+  get_string_rstrip(entry_point_name_buf, entry_point_name, NAME_LEN);
+ printf("%s:%s\n", entryname_buf, entry_point_name_buf);
+
+  *ref_pointer =
+    entry_point_name_buf[0] ?
+      find_definition(
+        link_segment(entryname_buf),
+        entry_point_name_buf,
+        -1,
+        false
+      ) :
+      its_pointer(make_known(entryname_buf)->segment, 0);
+
+  fprintf(
+    stderr,
+    "make_ptr %s$%s -> %06o:%06o\n",
+    entryname_buf,
+    entry_point_name_buf,
+    ref_pointer->segment,
+    ref_pointer->address
+  );
+
+  *code = 0;
+}
+
 int main(int argc, char **argv) {
   bool af = false;
   if (argc >= 2 && strcmp(argv[1], "--af") == 0) {
@@ -603,7 +690,7 @@ int main(int argc, char **argv) {
     //DBG_ADDRMOD |
     //DBG_APPENDING |
     //DBG_TRACEEXT |
-    //DBG_WARN |
+    DBG_WARN |
     //DBG_DEBUG |
     //DBG_INFO |
     //DBG_NOTIFY |
@@ -656,7 +743,7 @@ int main(int argc, char **argv) {
   stack_header->isot_ptr = its_pointer(linkage_segment, isot_offset);
 
   // load pl1 operators
-  struct loaded_segment *p = load_segment(xlate_segment("pl1_operators_"));
+  struct known_segment *p = link_segment("pl1_operators_");
   struct its_pointer operator_table_pointer = find_definition(
     p,
     "operator_table",
@@ -768,6 +855,15 @@ int main(int argc, char **argv) {
     allocate_stack(0, 8)
   );
 
+  // create emcall stubs
+  emcall_stubs_offset = allocate_linkage(3, 1);
+  uint64_t *emcall_stubs = (uint64_t *)(
+    M[linkage_segment] + emcall_stubs_offset
+  );
+  emcall_stubs[0] = 0700046272120L; // tsp2 pr7|46,n* alm_entry
+  emcall_stubs[1] = 0000027420400L; // emcall make_ptr
+  emcall_stubs[2] = 0700044710120L; // tra pr7|44,n* alm_return_no_pop
+
   // create calling stub
   int calling_stub_offset = allocate_linkage(2, 1);
   uint64_t *calling_stub = (uint64_t *)(
@@ -780,7 +876,7 @@ int main(int argc, char **argv) {
   calling_stub[0] = 0000622700100L; // tsx0 pr0|402 call_ext_out_desc
   calling_stub[1] = 0000026420400L; // emcall exit_emulation
 
-  cpu.rA = (word36)(n_args_af) << 19;
+  cpu.rA = (word36)n_args_af << 19;
   cpu.rX[1] = arg_list_offset;
 
   cpu.PR[0].RNR = 3;
@@ -788,7 +884,7 @@ int main(int argc, char **argv) {
   cpu.PR[0].WORDNO = operator_table_pointer.address;
 
   struct its_pointer entry_pointer = find_definition(
-    load_segment(xlate_segment(entry_segname)),
+    link_segment(entry_segname),
     entry_name,
     -1,
     true
@@ -814,15 +910,12 @@ int main(int argc, char **argv) {
 
   // print result string
   if (af) {
-    char text[RESULT_LEN + 1];
+    char buf[RESULT_LEN + 1];
     uint64_t *result = (uint64_t *)(M[stack_segment] + result_offset);
-    int len = (int)(*result++ & 0777777);
-    rassert(len < sizeof(text));
-    static int shifts[4] = {27, 18, 9, 0};
-    for (int i = 0; i < len; ++i)
-      text[i] = (char)(result[i >> 2] >> shifts[i & 3]);
-    text[len] = 0;
-    printf("%s\n", text);
+    int result_len = (int)(*result++ & 0777777);
+    rassert(result_len < sizeof(buf));
+    get_string(buf, result, result_len);
+    printf("%s\n", buf);
   }
 
   return 0;