?? RIGHT := 110 ??
MODULE ocm$process_b0_instructions;
*copyc osd$default_pragmats
?? PUSH (LISTEXT := ON) ??
*copyc llt$section_definition
*copyc llt$segment_definition
*copyc llt$obsolete_segment_definition
*copyc llt$object_text_descriptor
*copyc llt$module_dictionary
*copyc llt$load_module
*copyc llt$section_address
*copyc oct$bytes
*copyc oct$single_module_predictor_hdr
*copyc oct$offset_change_list
*copyc oct$section_offset_changes
*copyc oce$metapatch_generator_errors
*copyc ocp$new_offset
*copyc osp$set_status_abnormal
?? POP ??

?? EJECT ??
?? TITLE := 'ocp$get_new_q_field' ??
*copyc och$get_new_q_field

  PROCEDURE ocp$get_new_q_field (current_offset: llt$section_address_range;
        old_q_field: oct$two_bytes;
        section_offset_cv: ^oct$offset_change_list;
    VAR new_q_field: oct$two_bytes);

    FUNCTION complement (old_q_field: oct$two_bytes): oct$two_bytes;

      IF old_q_field = 0 THEN
        complement := 0;
      ELSE
        complement := 0ffff(16) - old_q_field + 1;
      IFEND;

    FUNCEND complement;

?? EJECT ??

    VAR
      callee_offset: llt$section_address_range,
      distance: llt$section_address_range,
      new_callee_offset: llt$section_address_range,
      new_current_offset: llt$section_address_range,
      q_field: oct$two_bytes,
      sign_bit: 0 .. 1;

    sign_bit := old_q_field DIV 8000(16);
    IF sign_bit = 1 THEN
      q_field := complement (old_q_field);
      callee_offset := (((current_offset - (8 * q_field)) DIV 8) * 8);
    ELSE
      callee_offset := (((current_offset + (8 * old_q_field)) DIV 8) * 8);
    IFEND;
    new_callee_offset := ocp$new_offset (callee_offset, section_offset_cv);
    new_current_offset := ocp$new_offset (current_offset, section_offset_cv);
    IF ((new_callee_offset - callee_offset) = (new_current_offset - current_offset)) THEN
      new_q_field := old_q_field;
    ELSE
      distance := new_callee_offset - new_current_offset;
      IF distance < 0 THEN
        new_q_field := complement (((distance * ( - 1)) DIV 8) MOD 10000(16));
      ELSE
        new_q_field := ((distance + 7) DIV 8) MOD 10000(16);
      IFEND;
    IFEND;
  PROCEND ocp$get_new_q_field;

?? EJECT ??
?? TITLE := 'ocp$process_b0_instructions' ??

*copyc och$process_b0_instructions

  PROCEDURE [XDCL] ocp$process_b0_instructions (p_module_predictor: ^SEQ ( * );
        module_dictionary: ^llt$module_dictionary;
        p_int_ol: ^SEQ ( * );
    VAR status: ost$status);

    VAR
      byte_count: llt$section_length,
      code_section_found: boolean,
      current_offset: llt$section_address_range,
      data_descriptor: ^oct$four_bytes,
      int_ol: ^SEQ ( * ),
      j: llt$section_ordinal,
      new_q_field: oct$two_bytes,
      module_header: ^llt$load_module_header,
      module_number: llt$module_index,
      module_predictor: ^SEQ ( * ),
      module_predictor_hdr: ^oct$single_module_predictor_hdr,
      object_text_descriptor: ^llt$object_text_descriptor,
      obsolete_segment_definition: ^llt$obsolete_segment_definition,
      op_code: ^oct$one_byte,
      pva: ^cell,
      q_field: ^oct$two_bytes,
      rest_of_32_bits: ^oct$three_bytes,
      rest_of_16_bits: ^oct$one_byte,
      section_definition: ^llt$section_definition,
      section_definitions: ^llt$object_text_descriptor,
      section_header: ^oct$section_info,
      section_offset_cvs: ^oct$section_offset_changes,
      segment_definition: ^llt$segment_definition,
      socv: ^oct$offset_change_list;

    int_ol := p_int_ol;
    module_predictor := p_module_predictor;

    code_section_found := FALSE;
    RESET module_predictor;
    NEXT module_predictor_hdr IN module_predictor;
    IF module_predictor_hdr^.length_normal_section_ocv > 0 THEN
      section_offset_cvs := #PTR (module_predictor_hdr^.section_offset_cv, module_predictor^);
      RESET module_predictor TO section_offset_cvs;
      FOR j := 1 TO module_predictor_hdr^.length_normal_section_ocv DO
        NEXT section_header IN module_predictor;
        NEXT socv: [1 .. section_header^.number_of_socv_items] IN module_predictor;
        IF section_header^.section_kind = llc$code_section THEN
          module_number := 1;
          REPEAT
            IF (module_dictionary^ [module_number].name = module_predictor_hdr^.module_name) AND
                  (module_dictionary^ [module_number].kind = llc$load_module) THEN
              module_header := #PTR (module_dictionary^ [module_number].module_header, int_ol^);
              section_definitions := #PTR (module_header^.interpretive_header.section_definitions, int_ol^);
              RESET int_ol TO section_definitions;

              REPEAT
                NEXT object_text_descriptor IN int_ol;
                CASE object_text_descriptor^.kind OF

                = llc$obsolete_allotted_seg_def =
                  NEXT obsolete_segment_definition IN int_ol;
                  IF (obsolete_segment_definition^.section_definition.kind = llc$code_section) AND (
                        obsolete_segment_definition^.section_definition.section_ordinal = section_header^.
                        section_ordinal) THEN
                    code_section_found := TRUE;
                  IFEND;

                = llc$allotted_segment_definition =
                  NEXT segment_definition IN int_ol;
                  IF (segment_definition^.section_definition.kind = llc$code_section) AND
                        (segment_definition^.section_definition.section_ordinal = section_header^.
                        section_ordinal) THEN
                    code_section_found := TRUE;
                  IFEND;

                = llc$allotted_section_definition =
                  NEXT section_definition IN int_ol;
                  IF (section_definition^.kind = llc$code_section) AND (section_definition^.section_ordinal =
                        section_header^.section_ordinal) THEN
                    code_section_found := TRUE;
                  IFEND;

                = llc$section_definition, llc$unallocated_common_block =
                  NEXT section_definition IN int_ol;

                = llc$obsolete_segment_definition =
                  NEXT obsolete_segment_definition IN int_ol;

                = llc$segment_definition =
                  NEXT segment_definition IN int_ol;

                ELSE
                  osp$set_status_abnormal (occ$status_id, oce$no_code_section, '', status);
                  RETURN;
                CASEND;
              UNTIL code_section_found;
            ELSE
              module_number := module_number + 1;
            IFEND;
          UNTIL code_section_found OR (module_number > UPPERBOUND (module_dictionary^));
          IF code_section_found THEN
            byte_count := 0;
            pva := #address (#ring (int_ol), #segment (int_ol), object_text_descriptor^.allotted_section);
            RESET int_ol TO pva;
            WHILE byte_count < section_definition^.length DO
              NEXT op_code IN int_ol;
              byte_count := byte_count + 1;
              CASE op_code^ OF
              = 00 .. 06(16), 08 .. 11(16), 14(16), 16(16) .. 1c(16), 1e(16) .. 2a(16), 2c(16) .. 37(16),
                    39(16) .. 3f(16) =
                NEXT rest_of_16_bits IN int_ol;
                byte_count := byte_count + 1;
              = 80(16) .. 0a5(16), 0a7(16) .. 0aa(16), 0ac(16) .. 0ae(16), 0b1(16) .. 0b5(16), 0be(16),
                    0bf(16), 0d0(16) .. 0df(16) =
                NEXT rest_of_32_bits IN int_ol;
                byte_count := byte_count + 3;
              = 70(16) .. 77(16) =
                NEXT rest_of_16_bits IN int_ol;
                NEXT data_descriptor IN int_ol;
                NEXT data_descriptor IN int_ol;
                byte_count := byte_count + 9;
              = 0e4(16), 0e5(16), 0e9(16), 0eb(16) =
                NEXT rest_of_32_bits IN int_ol;
                NEXT data_descriptor IN int_ol;
                NEXT data_descriptor IN int_ol;
                byte_count := byte_count + 11;
              = 0ed(16), 0f3(16), 0f4(16), 0f9(16) .. 0fb(16) =
                NEXT rest_of_32_bits IN int_ol;
                NEXT data_descriptor IN int_ol;
                byte_count := byte_count + 7;
              = 0b0(16) =
                current_offset := #offset (op_code) - #offset (pva);
                NEXT rest_of_16_bits IN int_ol;
                NEXT q_field IN int_ol;
                ocp$get_new_q_field (current_offset, q_field^, socv, new_q_field);
                q_field^ := new_q_field;
                byte_count := byte_count + 3;
              ELSE
                NEXT rest_of_16_bits IN int_ol;
                byte_count := byte_count + 1;
              CASEND;
            WHILEND;
          IFEND;
        IFEND;
      FOREND;
    IFEND;
  PROCEND ocp$process_b0_instructions;
MODEND ocm$process_b0_instructions;
