1 2 /* 3 The procedure cobol_call_gen generates the code necessary to imple- 4 ment the CALL statement. The general format of the CALL state- 5 ment is as follows: 6 7 C^H_A^H_L^H_L^H_ {literal-1|identifier-1} 8 [U^H_S^H_I^H_N^H_G^H_ data-name-1,[data-name-2]...] 9 10 The essential difference between CALL literal-1 and CALL identi- 11 fier-1 is the time at which the name of the program to be called 12 is known. In the case of CALL literal-1, the name is known at 13 compile time. Thus, a type 4 link can be created for the program 14 at compile time, which is "snapped" by the Dynamic Linker at ex- 15 ecution time, and thereby replaced by a pointer to the program's 16 entry point. In the case of CALL identifier-1, the name of the 17 program to be called is known only at execution time. Thus, an 18 execution time call to system sybroutine hcs_$make_ptr is neces- 19 sary to obtain a pointer to the program's entry point. In both 20 cases, however, standard MULTICS call conventions are employed to 21 make the actual "call" to the specified program. 22 23 It should be noted that the content of literal-1 and identifier-1 24 may consist of a segment name and/or an entry point name as follows: 25 26 Form 1 27 segment_name$entry_point_name 28 29 Form2 30 entry_point_name 31 32 Form 1 must be used if the name of the segment containing the 33 program and the name of the program's entry point are different, 34 but it may also be used if they are the same. Form 2 may only 35 be used if the name of the segment containing the program and the 36 name of the program's entry point are identical. 37 38 U^H__^Hs_^Ha_^Hg_^He:^H_ 39 40 declare cobol_call_gen entry (ptr); 41 call cobol_call_gen(in_token_ptr); 42 43 */ 44 45 46 /* 47 G^H__^He_^Hn_^He_^Hr_^Ha_^Ht_^He_^Hd_C^H__^Ho_^Hd_^He:^H_ 48 49 CALL identifier-1 50 51 To implement CALL identifier-1, it is necessary to call system 52 subroutine hcs_$make_ptr to obtain a pointer to the entry point 53 of the program named by identifier-1. This subroutine returns an 54 error code indicative of the system's success (code = 0) or fail- 55 ure (code /^H= 0) to obtain the pointer. Code is therefore generat- 56 ed to examine the returned error code and to report any problem 57 to the user via the run-time routine cobol_error_. The sequences 58 of code shown below are used to make the call to hcs_$make_ptr 59 and to examine the error code returned by it. The call to cobol_ 60 error_ is generated by cobol_gen_error. 61 62 Five parameters are passed to hcs_$make_ptr. They are: 63 64 caller_ptr by standard usage a null ptr (Input). 65 66 seg_name the name of the segment to be located (Input). 67 68 e_p_name the name of the entry point to be located (Input). 69 70 e_p_ptr the pointer to the segment entry point specified by 71 seg_name and e_p_name (Output). 72 73 error_code the returned error code (Output). 74 75 The argument list passed to hcs_$make_ptr must include pointers 76 to descriptors for the parameters as well as pointers to the par- 77 ameters themselves inasmuch as seg_name and e_p_name are describ- 78 ed as char(*). 79 80 Sequence 1-1 81 82 The code comprising Sequence 1-1 establishes pointers in the ar- 83 gument list to be passed to hsc_$make_ptr for all parameters ex- 84 cept seg_name and e_p_name. 85 86 epp2 n_relp,ic* 87 spri2 pr6|M+2 88 epp2 pr6|M+2 89 spri2 pr6|M+10 90 epp2 pr6|M 91 spri2 pr6|M+16 92 epp2 pr6|40 93 spri2 pr6|M+18 94 epp2 ptr_d_relp,1c 95 spri2 pr6|M+20 96 spri2 pr6|M+26 97 epp2 fb_d_relp,ic 98 spri2 pr6|M+28 99 100 Sequence 1-2 101 102 The function of Sequence 1-2 is to develop a pointer to identifi- 103 er-1 in pointer register 2 and to store this in the argument list 104 to be passed to hcs_$make_ptr as the pointer to seg_name. If 105 identifier-1 does not contain a $, it will also be stored in the 106 argument list as the pointer to e_p_name (see Sequence 1-3). 107 108 The address of identifier-1 will always involve the contents of a 109 pointer register (pri) and a word offset (wo), which may be zero. 110 It may also involve a character offset (co) and/or the contents 111 of the a, q, or some index register (ra). Thus, there are four 112 possibilities for the code sequence used to develop the pointer 113 to identifier-1, as follows: 114 115 A - No character offset, no register 116 117 epp2 pri|wo 118 spri2 pr6|M+12 119 120 B - Character offset, no register 121 122 epp2 pri|wo 123 lda co,dl 124 a9bd pr2|0,a 125 spri2 pr6|M+12 126 127 c - No character offset, register 128 129 epp2 pri|wo 130 a9bd pr2|0,ra 131 spri2 pr6|M+12 132 133 D - Character offset, register 134 135 epp2 pri|wo 136 a9bd pr2|0,ra 137 lda co,dl 138 a9db pr2|0,a 139 spri2 pr6|M+12 140 141 142 In the event that identifier-1 is a variable length data item, 143 instructions to compute its length and store the result in an 144 index register will have been generated by a utility called by 145 cobol_call_gen prior to the generation of Sequence 1-2 code. In 146 this case, Sequence 1-2 code will include two additional instruc- 147 tions to store the length from the index register into location 148 pr6|42 in the caller's stack frame. These instructions are as 149 follows: 150 151 stz pr6|42 152 sxln pr6|42 153 154 Sequence 1-3 155 156 This code sequence performs the following functions: 157 158 - Develops a pointer to e_p_name and stores it in the argument 159 list. 160 161 - Determines the length of and develops descriptors for seg_ 162 name and e_p_name. 163 164 - Develops pointers to descriptors for all parameters to be 165 passed to hcs_$make_ptr and stores them in the argument 166 list. 167 168 - Invokes cobol call operator call_ext_out_desc. 169 170 scm (pr,[rl]),(du),mask(0) 171 adsc9 pr2|0,{l or xn} 172 vfd o9/044,27/0 173 arg pr6|M+5 174 ttn 16,ic 175 lda pr6|M+5 176 ora 174080,du 177 sta pr6|M+6 178 lda pr6|M+5 179 ada 1,dl 180 a9bd pr2|0,a 181 spri2 pr6|M+14 182 neg 183 ada l,dl or pr6|42 184 ora 174080,du 185 sta pr6|M+7 186 epp2 pr6|M+6 187 spri2 pr6|M+22 188 epp2 pr6|M+7 189 tra 7,ic 190 spri2 pr6|M+14 191 ldq l,dl or pr6|42 192 orq 174080,du 193 stq pr6|M+6 194 epp2 pr6|M+6 195 spri2 pr6|M+22 196 spri2 pr6|M+24 197 eax1 pr6|M+8 198 fld 10240,dl 199 epp2 pr4|m_pt_e,* 200 tsx0 pr0|call_eod 201 202 Sequence 2-0 203 204 The function of the code generated by Sequence 2-0, either di- 205 rectly or by utilities called by cobol_call_gen, is to examine the 206 error code returned by hcs_$make_ptr and, in the event that it is 207 not zero, to report the nature of the error to the user. 208 209 [Code generated by cobol_reg_manager$after_op to reset pr3, pr4, ] 210 [and, if necessary, pr5. ] 211 lda pr6|M+4 212 tze call_relp,ic 213 [Code generated by cobol_gen_error to call cobol_error_ and] 214 [reset pr3, pr4, and, if necessary, pr5. ] 215 tra seq1-1_relp,ic 216 217 The symbols used in the above code sequences are defined as 218 follows: 219 220 M is the word offset in the caller's stack frame of the 221 next available even-numbered word. 222 223 n_relp is the offset, relative to the instruction in which 224 it is used, of a null pointer in the Constant Sec- 225 tion of the Text Segment. 226 227 ptr_d_relp is the offset, relative to the instruction in which 228 it is used, of a pointer descriptor located in the 229 Constant Segment of the Text Segment. 230 231 fb_d_relp is the offset, relative to the instruction in which 232 it is used, of a descriptor for a real fixed binary 233 short quantity located in the Constant Section of the 234 Text Segment. 235 236 call_relp is the offset, relative to the instruction in which 237 it is used, of the first instruction of the standard 238 MULTICS call sequence generated to call identifier-1. 239 240 seq1-1_relp is the offset, relative to the instruction in which 241 it is used, of the first instruction of Sequence 1-1. 242 243 m_pt_e is the offset, relative to the base of the MULTICS 244 Linkage Section, of a pointer (initially a link 245 created by a call to cobol_make_link$type_4) to the entry 246 point of subroutine hcs_$make_ptr. 247 248 call_eod is the location, relative to the label operator_table 249 in cobol_operators, of the first instruction of the cobol 250 call operator call_ext_out_desc. The current value 251 of call_eod is 5. 252 253 All other symbols are defined as used. 254 255 256 Standard MULTICS call 257 258 A standard MULTICS call is used in the implementation of both 259 CALL literal-1 and CALL identifier-1. The code generated to im- 260 plement a standard MULTICS call comprises three sequences of in- 261 structions. Sequences 1 and 2 are omitted, however, if the GO 262 statement does not contain the USING phrase. 263 264 Sequence 1 - The function of this sequence of instructions is to 265 create pointers to the USING phrase operands and place them in an 266 argument list in the caller's stack frame. Sequence 1a is used 267 for operands defined in the File Section, Working-Storage Sec- 268 tion, or Communication Section. Sequence 1b is used for operands 269 defined in the COBOL Linkage Section. The appropriate sequence, 270 1a or 1b, is generated once per operand in the order of its ap- 271 pearance in the USING phrase. Consequently, the pointers are 272 similarly arranged in the argument list. It should be noted that 273 two words are reserved at the top of the argument list for a 274 header which is inserted by the appropriate cobol call operator 275 (see Sequence 3). 276 277 Sequence 1a 278 279 epp2 oprnd_z 280 spri2 pr6|N+2z 281 282 Sequence 1b 283 284 [epp1 pr6|26,*] see note 285 epp2 pr1|2y,* 286 spri2 pr6|N+2z 287 288 Note: pr6|26 contains a pointer to the argument list passed to 289 the caller by it's caller. This instruction is generated 290 only once per call when the first USING phrase operand de- 291 fined in the COBOL Linkage Section is encountered. 292 293 Sequence 2 - The function of this sequence of instructions is to 294 create pointers to descriptors for the USING phrase operands and 295 place them in the argument list following the pointers generated 296 by Sequence 1 instructions. The sequence is repeated as required 297 to place one pointer per operand into the argument list. 298 299 Sequence 2 300 301 epp2 desc_l,ic 302 spri2 pr6|N+2zt+2za 303 spri2 pr6|N+2zt+2zb 304 spri2 pr6|N+2zt+2zc 305 . . . . . 306 . . . . . 307 . . . . . 308 309 Sequence 3 - The function of this sequence of instructions is to 310 establish the conditions necessary for invoking an appropriate 311 cobol call operator. Sequence 3a is used when the optional USING 312 phrase is present. It invokes the operator call_ext_out_desc. 313 Sequence 3b is used when the optional USING phrase is not pre- 314 sent. It invokes the operator call_ext_out. 315 316 Sequence 3a 317 318 eax1 pr6|N 319 fld 2**11 zt,dl 320 epp2 e_p_ptr,* 321 tsx0 pr0|call_eod 322 323 Sequence 3b 324 325 eax1 pr6|46 326 fld 0,dl 327 epp2 e_p_ptr,* 328 tsx0 pr0|call_eo 329 330 In the above sequences - 331 332 N is the offset in the caller's stack frame of the first 333 word of the argument list to be passed to the program 334 named in literal-1 or identifier-1. It must be located 335 on a double word boundary. 336 337 zt is the total number of operands in the CALL statement 338 USING phrase. 339 340 z is a number designating the position of an operand in 341 the CALL statement USING phrase; z = 1, 2, 3, ... zt. 342 343 oprnd_z is the zth operand of the CALL statement USING phrase. 344 345 y is a number designating the position of operand z of the 346 CALL statement USING phrase in the Procedure Division 347 header USING phrase when operand z is defined in the 348 COBOL Linkage Section. 349 350 desc_l is a descriptor for a character string of length l. 351 352 zx for x = a, b, c, ..., are the positions within the CALL 353 statement USING phrase of those operands whose length is 354 l characters. 355 356 e_p_ptr is a pointer to the entry point of the program named in 357 literal-1 or identifier-1. In the case of literal-1, 358 this pointer is located in the MULTICS linkage section 359 and is initially a type 4 link created at compile time. 360 In the case of identifier-1, the pointer is located in 361 the caller's stack frame. Its value is determined by an 362 execution time call to system subroutine hcs_$make_ptr. 363 364 call_eop is the location, relative to the label operator_table in 365 cobol_operators, of the first instruction of the cobol call 366 operator call_ext_out_desc. The current value of 367 call_eod is 5. 368 369 call_eo is the location, relative to the label operator_table in 370 cobol_operators, of the first instruction of the cobol call 371 operator call_ext_out. The current value of call_eo is 372 6. 373 374 R^H__^He_^Hl_^Ho_^Hc_^Ha_^Ht_^Hi_^Ho_^Hn_I^H__^Hn_^Hf_^Ho_^Hr_^Hm_^Ha_^Ht_^Hi_^Ho_^Hn:^H_ 375 376 All instructions generated directly by procedure cobol_call_gen (as 377 opposed to being generated by a utility called cobol_call_gen) are 378 non-relocatable with the following exceptions: 379 380 The left hand (address) half of the instruction 381 382 epp2 pr4|m_ptr,* 383 384 in Sequence 3_1. 385 386 The left hand (address) half of the instruction 387 388 epp2 e_p_ptr,* 389 390 in Sequence 3 when it is generated to implement CALL literal-1. 391 392 In both cases the entity referenced is a type 4 link located in 393 the Linkage Section using pointer register 4. The relocation 394 code generated for these instruction halfwords is "10100"b. 395 396 */ 397 /* 398 D^H__^Ha_^Ht_^Ha:^H_ 399 400 Items in cobol_$incl.cobol used (u) and/or set (s) by 401 cobol_call_gen: 402 403 cobol_ptr (u) 404 next_tag (u/s) 405 text_wd_off (u) 406 407 */ 408 409 410 411 /* Input structure used for cobol_pointer_register$get. */ 412 413 declare 1 register_request aligned static, 414 2 what_pointer fixed bin aligned init(1), 415 2 assigned_ptr fixed bin aligned, 416 2 lock fixed bin aligned init(1), 417 2 switch fixed bin aligned init(0), 418 2 segno fixed bin aligned init(0), 419 2 offset fixed bin aligned init(0), 420 2 reset fixed bin aligned; 421 422 /* 423 where: 424 425 what_pointer is the number of the desired pointer register. 426 (Input) 427 428 assigned_ptr is the number of the register assigned. (Output) 429 430 lock specifies locking requirements. (1 - lock 431 requested register). (Input) 432 433 switch specifies the significance of segno and offset. 434 (0 - segno and word offset are not supplied). 435 (Input) 436 437 segno is the segment number that the pointer register is 438 to contain. (Input) 439 440 offset is the word or character offset that the pointer 441 reginter is to contain. (Input) 442 443 */ 444