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