C P / M   6 8 0 0 0   A s s e m b l e r		Revision 02.03		Page   1
Source File: pgmld.s

   1                               
   2                               *********************************
   3                               *                               *
   4                               *  Function 59 -- Program Load  *
   5                               *   Assembly language version   *
   6                               *                               *
   7                               *        June  8, 1982          *
   8                               *                               *
   9                               *********************************
  10                               
  11                               .globl  _pgmld          * this routine is public
  12                               
  13                               secsize = 128           * CP/M sector size
  14                               
  15                               * d0 always contains the return parameter from pgmld
  16                               * d1 is the return register from local subroutines
  17                               * a0 contains the pointer to the Load Parm Block passed to pgmld
  18                               
  19                               * Return parameters in d0 are:
  20                               *       00 - function successful
  21                               *       01 - insufficient memory or bad header in file
  22                               *       02 - read error on file
  23                               *       03 - bad relocation information in file
  24                               
  25                               
  26                               * Entry point for Program Load routine
  27                               _pgmld:
  28 00000000 48E77FFE                     movem.l d1-d7/a0-a6, -(sp) * save everything, just to be safe
  29 00000004 206F003C                     move.l  60(sp),a0       * get pointer to LPB
  30 00000008 4280                         clr.l   d0              * start with return parm cleared
  31 0000000A 6154                         bsr     gethdr          * get header
  32 0000000C 4A40                         tst     d0
  33 0000000E 662A                         bne     lddone          * if unsuccessful, return
  34 00000010 61000108                     bsr     setaddr         * set up load addresses
  35 00000014 4A40                         tst     d0
  36 00000016 6622                         bne     lddone          * if unsuccessful, return
  37 00000018 61000258                     bsr     rdtxt           * read code and data text segments into mem
  38 0000001C 4A40                         tst     d0
  39 0000001E 661A                         bne     lddone          * if unsuccessful, return
  40 00000020 2E3900000016                 move.l  tstart,d7
  41 00000026 BEB900000024                 cmp.l   cseg,d7
  42 0000002C 6704                         beq     noreloc
  43 0000002E 61000350                     bsr     reloc           * do relocation if necessary
  44                               noreloc:
  45 00000032 4A40                         tst     d0
  46 00000034 6604                         bne     lddone
  47 00000036 610003E8                     bsr     setrtn          * set up return parameters
  48                               lddone:
  49 0000003A 222F0040                     move.l  64(sp), d1
  50 0000003E 6116                         bsr     setdma          * restore dma address
  51 00000040 4CDF7FFE                     movem.l (sp)+,d1-d7/a0-a6
  52 00000044 4E75                         rts
  53                               
  54                               * Subroutines
  55                               
C P / M   6 8 0 0 0   A s s e m b l e r		Revision 02.03		Page   2
Source File: pgmld.s

  56                               readseq:
  57                               * CP/M read sequential function
  58 00000046 2F00                         move.l  d0,-(sp)        * save return parm
  59 00000048 22280000                     move.l  FCBPtr(a0),d1
  60 0000004C 7014                         moveq   #20,d0          * read seq function
  61 0000004E 4E42                         trap    #2              * call bdos
  62 00000050 2200                         move.l  d0,d1           * return parm in d1
  63 00000052 201F                         move.l  (sp)+,d0
  64 00000054 4E75                         rts
  65                               
  66                               
  67                               setdma:
  68                               * CP/M set dma function
  69 00000056 2F00                         move.l  d0,-(sp)        * save return parm
  70 00000058 701A                         moveq   #26,d0          * set dma function
  71 0000005A 4E42                         trap    #2              * call bdos
  72 0000005C 201F                         move.l  (sp)+,d0        * restore d0
  73 0000005E 4E75                         rts
  74                               
  75                               
  76                               gethdr:
  77                               * Get header into buffer in data segment
  78 00000060 22280004                     move.l  LoAdr(a0),d1
  79 00000064 61F0                         bsr     setdma
  80 00000066 61DE                         bsr     readseq
  81 00000068 4A41                         tst     d1              * read ok?
  82 0000006A 6614                         bne     badhdr          * if no, return bad
  83 0000006C 7E12                         moveq   #18,d7
  84 0000006E 2A680004                     movea.l LoAdr(a0),a5
  85 00000072 2C7C00000000                 movea.l #hdr,a6
  86 00000078 3CDD                 geth1:  move.w  (a5)+,(a6)+     * move header into hdr
  87 0000007A 51CFFFFC                     dbf     d7,geth1
  88 0000007E 4E75                         rts
  89 00000080 7002                 badhdr: moveq   #2,d0
  90 00000082 4E75                         rts
  91                               
  92                               
  93                               conflict:
  94                               * input parms: d2, d3 = 4 * segment nmbr
  95                               * if segment d2/4 overlaps segment d3/4, then return 1 in d1
  96                               * else return 0 in d1
  97                               * uses d7, a2, a3
  98 00000084 4281                         clr.l   d1              * assume it will work
  99 00000086 247C00000024                 movea.l #cseg,a2        * a2 points to start of segment addresses
 100 0000008C 267C00000002                 movea.l #csize,a3       * a3 points to start of segment lengths
 101 00000092 2E322000                     move.l  0(a2,d2),d7     * get 1st seg start
 102 00000096 BEB23000                     cmp.l   0(a2,d3),d7     * is 1st seg above 2nd seg?
 103 0000009A 6C0C                         bge     conf1
 104 0000009C DEB32000                     add.l   0(a3,d2),d7     * yes, find top of 1st seg
 105 000000A0 BEB23000                     cmp.l   0(a2,d3),d7     * above start of 2nd seg?
 106 000000A4 6E10                         bgt     confbd          * if yes, we have a conflict
 107 000000A6 4E75                         rts                     * else, return good
 108                               conf1:
 109 000000A8 2E323000                     move.l  0(a2,d3),d7
 110 000000AC DEB33000                     add.l   0(a3,d3),d7     * find top of 2nd seg
C P / M   6 8 0 0 0   A s s e m b l e r		Revision 02.03		Page   3
Source File: pgmld.s

 111 000000B0 BEB22000                     cmp.l   0(a2,d2),d7     * above start of 1st seg?
 112 000000B4 6F02                         ble     confgd          * if no, we're ok
 113 000000B6 7201                 confbd: moveq.l #1,d1
 114 000000B8 4E75                 confgd: rts
 115                               
 116                               
 117                               trymemtp:
 118                               * entry: d2 is a segment nmbr [0..4]
 119                               * try to fit it at top of memory
 120                               * uses d3, d6, d7, a5, a6
 121                               * returns 0 in d1 if ok
 122 000000BA 2C02                         move.l  d2,d6           * d6 is loop counter for chksegs
 123 000000BC 5346                         subq    #1,d6
 124 000000BE E54A                         lsl     #2,d2           * multiply d2 by 4
 125 000000C0 2E280008                     move.l  HiAdr(a0),d7    * top of mem to d7
 126                               
 127                               chksegs:
 128                               * entry: d2 = 4 * (segment nmbr to try)
 129                               *        d6 = (d2/4) - 1  (loop counter)
 130                               *        d7 = address below which to try it
 131                               * check for conflicts with segments [0..d6] and low memory boundary
 132                               * return 0 in d1 if no conflicts, else d1 = 1
 133                               * uses d3, a5, a6
 134 000000C4 2A7C00000024                 movea.l #cseg,a5
 135 000000CA 2C7C00000002                 movea.l #csize,a6
 136 000000D0 9EB62000                     sub.l   0(a6,d2),d7     * subtract size of segment to try
 137 000000D4 08870000                     bclr    #0,d7           * make it even address
 138 000000D8 2B872000                     move.l  d7,0(a5,d2)     * insert address in segment table
 139 000000DC BEA80004                     cmp.l   LoAdr(a0),d7    * check for conflict with low memory
 140 000000E0 6DD4                         blt     confbd
 141 000000E2 4283                         clr.l   d3              * check for conflicts with 0..d6
 142                               chk1:
 143 000000E4 619E                         bsr     conflict
 144 000000E6 5883                         addq.l  #4,d3
 145 000000E8 4A81                         tst.l   d1              * conflict with this seg?
 146 000000EA 56CEFFF8                     dbne    d6,chk1         * if no, try next
 147 000000EE 4E75                         rts
 148                               
 149                               
 150                               fndseg:
 151                               * entry: d2 is a segment nmbr [0..4]
 152                               * try to fit segment d2 directly below segments 0..(d2-1)
 153                               * uses d3-d7, a5, a6
 154 000000F0 2A02                         move.l  d2,d5           * d5 is loop counter to find fit
 155 000000F2 5385                         subq.l  #1,d5
 156 000000F4 23C50000003C                 move.l  d5,temp
 157 000000FA E58A                         lsl.l   #2,d2           * multiply segment by 4
 158 000000FC 4284                         clr.l   d4              * d4 is segment to try to fit below
 159                               fnd1:
 160 000000FE 2C390000003C                 move.l  temp,d6         * d6 is loop counter for chksegs
 161 00000104 2A7C00000024                 movea.l #cseg,a5
 162 0000010A 2E354000                     move.l  0(a5,d4),d7     * segment address to d7
 163 0000010E 61B4                         bsr     chksegs         * check for conflicts
 164 00000110 5884                         addq.l  #4,d4
 165 00000112 4A81                         tst.l   d1
C P / M   6 8 0 0 0   A s s e m b l e r		Revision 02.03		Page   4
Source File: pgmld.s

 166 00000114 57CDFFE8                     dbeq    d5,fnd1         * if conflict, try next
 167 00000118 4E75                         rts
 168                               
 169                               
 170                               setaddr:
 171                               * Set up load addresses for cseg, dseg, bss, basepg, and stack
 172 0000011A 3C3900000000                 move.w  magic,d6
 173 00000120 0246FFFE                     andi.w  #$fffe,d6
 174 00000124 0C46601A                     cmpi.w  #$601a,d6
 175 00000128 66000120                     bne     badadr          * if magic nmbr <> 601a or 601b, skip
 176 0000012C 23F90000000E00000038         move.l  bpsize,symsize
 177 00000136 2E3C00000100                 move.l  #256,d7
 178 0000013C 23C70000000E                 move.l  d7,bpsize       * base page is 256 bytes
 179 00000142 45F900000012                 lea     stksize,a2
 180 00000148 BE52                         cmp     (a2),d7
 181 0000014A 6D02                         blt     set0            * if stack size < 256, set to 256
 182 0000014C 2487                         move.l  d7,(a2)
 183 0000014E 0C79601B00000000     set0:   cmpi.w  #$601b,magic
 184 00000156 6708                         beq     seta
 185 00000158 4A790000001A                 tst.w   rlbflg
 186 0000015E 670C                         beq     set1
 187 00000160 23F90000001600000024 seta:   move.l  tstart,cseg     * if not relocatable or hdr = $601b,
 188 0000016A 6040                         bra     set2            * cseg starts at tstart
 189 0000016C 082800000015         set1:   btst    #0,Flags(a0)
 190 00000172 6616                         bne     sldhi
 191                               * relocatable, load low
 192 00000174 2E280004                     move.l  LoAdr(a0),d7
 193 00000178 DEBC00000101                 add.l   #$101,d7        * leave room for base page
 194 0000017E 08870000                     bclr    #0,d7
 195 00000182 23C700000024                 move.l  d7,cseg         * cseg is bottom of mem + $100 (even boundary)
 196 00000188 6022                         bra     set2
 197                               sldhi:
 198                               * relocatable, load high
 199 0000018A 2E280008                     move.l  HiAdr(a0),d7
 200 0000018E 9EB900000002                 sub.l   csize,d7
 201 00000194 9EB900000006                 sub.l   dsize,d7
 202 0000019A 9EB90000000A                 sub.l   bsize,d7
 203 000001A0 5987                         subq.l  #4,d7
 204 000001A2 08870000                     bclr    #0,d7           * put cseg at next even address below
 205 000001A6 23C700000024                 move.l  d7,cseg         *  high memory - (sum of sizes)
 206                               set2:
 207                               * Cseg has been set up.  Now do dseg, bseg
 208 000001AC 0C79601B00000000             cmpi.w  #$601b,magic
 209 000001B4 6616                         bne     set3
 210                               * if magic # = 601b, take addr from hdr
 211 000001B6 23F90000001C00000028         move.l  dstart,dseg
 212 000001C0 23F9000000200000002C         move.l  bstart,bseg
 213 000001CA 602A                         bra     set4
 214                               set3:
 215                               * if short header, dseg and bseg follow cseg
 216 000001CC 2E3900000024                 move.l  cseg,d7
 217 000001D2 DEB900000002                 add.l   csize,d7
 218 000001D8 5287                         addq.l  #1,d7
 219 000001DA 08870000                     bclr    #0,d7
 220 000001DE 23C700000028                 move.l  d7,dseg
C P / M   6 8 0 0 0   A s s e m b l e r		Revision 02.03		Page   5
Source File: pgmld.s

 221 000001E4 DEB900000006                 add.l   dsize,d7
 222 000001EA 5287                         addq.l  #1,d7
 223 000001EC 08870000                     bclr    #0,d7
 224 000001F0 23C70000002C                 move.l  d7,bseg
 225                               set4:
 226                               * cseg, dseg, bseg set up
 227                               * now find a place for the base page and stack
 228 000001F6 7403                         moveq.l #3,d2
 229 000001F8 6100FEF6                     bsr     fndseg          * try to fit base page below cseg, dseg, bseg
 230 000001FC 4A81                         tst.l   d1
 231 000001FE 670A                         beq     set5            * if found, skip
 232 00000200 7403                         moveq.l #3,d2
 233 00000202 6100FEB6                     bsr     trymemtp        * else, try top of memory
 234 00000206 4A81                         tst.l   d1
 235 00000208 6640                         bne     badadr          * if fail, exit
 236 0000020A 7404                 set5:   moveq.l #4,d2
 237 0000020C 6100FEAC                     bsr     trymemtp        * try to fit stack at top of memory
 238 00000210 4A81                         tst.l   d1
 239 00000212 670A                         beq     set6            * if ok, skip
 240 00000214 7404                         moveq.l #4,d2
 241 00000216 6100FED8                     bsr     fndseg          * else, try to fit below other segs
 242 0000021A 4A81                         tst.l   d1
 243 0000021C 662C                         bne     badadr
 244                               set6:
 245                               * now check all segments for conflicts with low and high memory boundaries
 246 0000021E 2A7C00000024                 movea.l #cseg,a5
 247 00000224 2C7C00000002                 movea.l #csize,a6
 248 0000022A 4282                         clr.l   d2
 249 0000022C 7604                         moveq   #4,d3           * loop counter
 250 0000022E 2E352000             set7:   move.l  0(a5,d2),d7     * get segment base
 251 00000232 BEA80004                     cmp.l   LoAdr(a0),d7    * above bottom of memory?
 252 00000236 6D12                         blt     badadr
 253 00000238 DEB62000                     add.l   0(a6,d2),d7     * find top of segment
 254 0000023C BEA80008                     cmp.l   HiAdr(a0),d7    * below top of memory?
 255 00000240 6E08                         bgt     badadr
 256 00000242 5882                         addq.l  #4,d2           * point to next segment
 257 00000244 51CBFFE8                     dbf     d3,set7
 258 00000248 4E75                         rts
 259 0000024A 7001                 badadr: moveq.l #1,d0
 260 0000024C 4E75                         rts
 261                               
 262                               
 263                               movebuf:
 264                               * move (d3) bytes from the base page buffer to (a2)
 265                               * uses d6
 266 0000024E 227900000030                 movea.l basepg,a1
 267 00000254 2C3C00000080                 move.l  #secsize,d6
 268 0000025A 9C7900000042                 sub.w   bufbyts,d6      * address to move from =
 269 00000260 D2C6                         adda.w  d6,a1           *       (basepg) + secsize - (bufbyts)
 270 00000262 977900000042                 sub.w   d3,bufbyts      * update # bytes buffered
 271 00000268 6002                         bra     moveb2
 272 0000026A 14D9                 moveb1: move.b  (a1)+,(a2)+     * do the move
 273 0000026C 51CBFFFC             moveb2: dbf     d3,moveb1
 274 00000270 4E75                         rts
 275                               
C P / M   6 8 0 0 0   A s s e m b l e r		Revision 02.03		Page   6
Source File: pgmld.s

 276                               
 277                               rdtxt:
 278                               * Read code and data text into memory
 279                               * during this routine, a2 is always the load address,
 280                               *                      d2 is number of bytes left to load
 281 00000272 7E3F                         moveq   #63,d7
 282 00000274 2A680004                     movea.l LoAdr(a0),a5
 283 00000278 2C7900000030                 movea.l basepg,a6
 284 0000027E 3CDD                 rdtxt1: move.w  (a5)+,(a6)+     * move header sector to base page
 285 00000280 51CFFFFC                     dbf     d7,rdtxt1
 286 00000284 3E3C0064                     move.w  #secsize-28,d7
 287 00000288 0C79601A00000000             cmpi.w  #$601a,magic    * short header?
 288 00000290 6702                         beq     rdtxt2
 289 00000292 5147                         subq.w  #8,d7
 290 00000294 33C700000042         rdtxt2: move.w  d7,bufbyts      * indicate # bytes of text in buffer
 291 0000029A 33FC000200000040             move.w  #2,loop         * do for code, data segments
 292 000002A2 247900000024                 move.l  cseg,a2         * start at cseg
 293 000002A8 243900000002                 move.l  csize,d2        * for csize bytes
 294                               rdtxt3:
 295 000002AE 4283                         clr.l   d3
 296 000002B0 363900000042                 move.w  bufbyts,d3
 297 000002B6 B682                         cmp.l   d2,d3           * # bytes in buffer >= # bytes to load?
 298 000002B8 6D06                         blt     rdtxt4
 299 000002BA 2602                         move.l  d2,d3
 300 000002BC 6190                         bsr     movebuf         * if yes, move # bytes to load
 301 000002BE 6048                         bra     finrd
 302                               rdtxt4:
 303 000002C0 9483                         sub.l   d3,d2           * if no, update # bytes to load
 304 000002C2 618A                         bsr     movebuf         * move remainder of buffer
 305 000002C4 263C00000080                 move.l  #secsize,d3     * d3 = secsize fo following loop
 306                               rdtxt5:
 307 000002CA B483                         cmp.l   d3,d2           * have at least one more full sector?
 308 000002CC 6D18                         blt     rdtxt6
 309 000002CE 220A                         move.l  a2,d1
 310 000002D0 6100FD84                     bsr     setdma          * if yes, set up dma address
 311 000002D4 6100FD70                     bsr     readseq         * read next sector
 312 000002D8 4A41                         tst.w   d1
 313 000002DA 6656                         bne     rdbad           * if no good, exit
 314 000002DC 9483                         sub.l   d3,d2           * decrement # bytes to load
 315 000002DE D5FC00000080                 adda.l  #secsize,a2     * increment dma address
 316 000002E4 60E4                         bra     rdtxt5
 317                               rdtxt6:
 318 000002E6 4A82                         tst.l   d2              * any more bytes to read?
 319 000002E8 671E                         beq     finrd
 320 000002EA 223900000030                 move.l  basepg,d1
 321 000002F0 6100FD64                     bsr     setdma
 322 000002F4 6100FD50                     bsr     readseq         * if yes, read into base page
 323 000002F8 4A41                         tst.w   d1
 324 000002FA 6636                         bne     rdbad
 325 000002FC 33C300000042                 move.w  d3,bufbyts      * indicate that we've buffered a sector
 326 00000302 2602                         move.l  d2,d3
 327 00000304 6100FF48                     bsr     movebuf         * move remainder of segment
 328                               finrd:
 329 00000308 247900000028                 move.l  dseg,a2         * set up to load data segment
 330 0000030E 243900000006                 move.l  dsize,d2
C P / M   6 8 0 0 0   A s s e m b l e r		Revision 02.03		Page   7
Source File: pgmld.s

 331 00000314 537900000040                 sub.w   #1,loop
 332 0000031A 6692                         bne     rdtxt3
 333 0000031C 24790000002C                 move.l  bseg,a2         * clear the bss segment
 334 00000322 24390000000A                 move.l  bsize,d2
 335 00000328 6706                         beq     rdtxt8
 336 0000032A 421A                 rdtxt7: clr.b   (a2)+
 337 0000032C 5382                         subq.l  #1,d2
 338 0000032E 66FA                         bne     rdtxt7
 339 00000330 4E75                 rdtxt8: rts
 340                               
 341 00000332 7002                 rdbad:  moveq.l #2,d0
 342 00000334 4E75                         rts
 343                               
 344                               
 345                               relocword:
 346                               * relocate word at (a2) based on reloc bits at (a3)
 347                               * lsb of d2 indicates whether previous word was 1st half of long-word
 348 00000336 3E1B                         move.w  (a3)+,d7        * get relocation info
 349 00000338 02470007                     andi.w  #7,d7           * strip off symbol table bits
 350 0000033C E34F                         lsl     #1,d7           * multiply by 2
 351 0000033E 4EFB7002                     jmp     2(pc,d7)
 352                               
 353 00000342 6014                         bra     relabs
 354 00000344 6022                         bra     reldata
 355 00000346 6020                         bra     relcode
 356 00000348 601E                         bra     relbss
 357 0000034A 6006                         bra     relbad
 358 0000034C 6012                         bra     rellong
 359 0000034E 6002                         bra     relbad
 360 00000350 6006                         bra     relop
 361                               
 362 00000352 201F                 relbad: move.l  (sp)+,d0        * pop return address
 363 00000354 7003                         moveq   #3,d0           * return bad relocation to main routine
 364 00000356 4E75                         rts
 365                               
 366                               relabs:
 367 00000358 08820000             relop:  bclr    #0,d2           * reset long word flag
 368 0000035C 4A5A                         tst.w   (a2)+           * point to next word of segment
 369 0000035E 4E75                         rts
 370                               
 371                               rellong:
 372 00000360 08C20000                     bset    #0,d2           * set long word flag
 373 00000364 4A5A                         tst.w   (a2)+           * point to next word of segment
 374 00000366 4E75                         rts
 375                               
 376                               reldata:
 377                               relbss:
 378                               relcode:
 379 00000368 08820000                     bclr    #0,d2           * long word flag set?
 380 0000036C 6608                         bne     relc1           * if yes, skip
 381 0000036E 3C12                         move.w  (a2),d6
 382 00000370 DC45                         add.w   d5,d6
 383 00000372 34C6                         move.w  d6,(a2)+
 384 00000374 4E75                         rts
 385                               
C P / M   6 8 0 0 0   A s s e m b l e r		Revision 02.03		Page   8
Source File: pgmld.s

 386 00000376 4A62                 relc1:  tst.w   -(a2)           * point to first word of long
 387 00000378 2C12                         move.l  (a2),d6
 388 0000037A DC85                         add.l   d5,d6
 389 0000037C 24C6                         move.l  d6,(a2)+        * note that a2 points past long word
 390 0000037E 4E75                         rts
 391                               
 392                               
 393                               reloc:
 394                               * Modify address references of code and data segments based on relocation bits
 395                               * During this routine,
 396                               * a2 points to text file to relocate
 397                               * a3 points to relocation word in basepg
 398                               * lsb of d2 is long word flag (set on reloc type 5, reset on next word)
 399                               * d3 is # words in relocation buffer
 400                               * d4 is nmbr of words left to relocate
 401                               * d5 is relocation offset
 402                               
 403 00000380 223900000030                 move.l  basepg,d1
 404 00000386 6100FCCE                     bsr     setdma          * we will always read into base page
 405                               * skip past the symbol table
 406 0000038A 2E3900000038                 move.l  symsize,d7
 407 00000390 8EFC0080                     divu    #secsize,d7     * calculate how many sectors to skip
 408                               * note that max # symbols is 8k, which is 896 sectors of 128 bytes
 409 00000394 3C07                         move.w  d7,d6           * d6 is nmbr sectors to skip
 410 00000396 4847                         swap    d7              * d7 is nmbr bytes to skip
 411 00000398 363900000042                 move.w  bufbyts,d3
 412 0000039E 9647                         sub.w   d7,d3           * subtract bytes to skip from buffer
 413 000003A0 6C06                         bge     skip1
 414 000003A2 06430080                     addi    #secsize,d3     *if amt in buffer < # bytes to skip,
 415 000003A6 5246                         addq    #1,d6           *  read in 1 extra sector
 416 000003A8 267900000030         skip1:  move.l  basepg,a3
 417 000003AE D6FC0080                     adda    #secsize,a3
 418 000003B2 96C3                         suba.w  d3,a3           * set up a3 to point to buffer
 419 000003B4 E24B                         lsr     #1,d3           * d3 is nmbr words in buffer
 420 000003B6 600A                         bra     skip3
 421                               skip2:
 422 000003B8 6100FC8C                     bsr     readseq         * read next symbol table sector
 423 000003BC 4A41                         tst.w   d1
 424 000003BE 6600FF72                     bne     rdbad
 425 000003C2 51CEFFF4             skip3:  dbf     d6,skip2
 426                               * we got past symbol table
 427                               * a3, d3 are set up
 428 000003C6 2A3900000024                 move.l  cseg,d5
 429 000003CC 2445                         move.l  d5,a2           * relocate cseg first
 430 000003CE 9AB900000016                 sub.l   tstart,d5       * d5 contains the relocation offset
 431 000003D4 283900000002                 move.l  csize,d4        * nmbr of bytes to relocate
 432 000003DA 33FC000200000040             move.w  #2,loop         * we're going to relocate 2 segments
 433                               reloc1:
 434                               * relocate one segment
 435 000003E2 4282                         clr.l   d2              * clear long word flag
 436 000003E4 E28C                         lsr.l   #1,d4           * make d4 indicate # words
 437 000003E6 601E                         bra     reloc4
 438                               reloc2:
 439 000003E8 5343                         subq.w  #1,d3
 440 000003EA 6A14                         bpl     reloc3
C P / M   6 8 0 0 0   A s s e m b l e r		Revision 02.03		Page   9
Source File: pgmld.s

 441 000003EC 6100FC58                     bsr     readseq         * if no more words in buffer, refill it
 442 000003F0 4A41                         tst.w   d1
 443 000003F2 6600FF3E                     bne     rdbad
 444 000003F6 267900000030                 move.l  basepg,a3
 445 000003FC 363C003F                     move.w  #(secsize/2)-1,d3
 446                               reloc3:
 447 00000400 6100FF34                     bsr     relocword       * relocate one word
 448 00000404 5384                         subq.l  #1,d4
 449                               reloc4:
 450 00000406 4A84                         tst.l   d4              * any more to relocate in this segment?
 451 00000408 66DE                         bne     reloc2          * if yes, do it
 452 0000040A 247900000028                 move.l  dseg,a2         * else, set up for dseg
 453 00000410 283900000006                 move.l  dsize,d4
 454 00000416 537900000040                 sub.w   #1,loop
 455 0000041C 66C4                         bne     reloc1
 456 0000041E 4E75                         rts
 457                               
 458                               
 459                               setrtn:
 460                               * Set up the return parameters in Ld Parm Blk and Base Page
 461 00000420 217900000030000C             move.l  basepg,BasPage(a0)
 462 00000428 2E3900000034                 move.l  stk,d7
 463 0000042E DEB900000012                 add.l   stksize,d7
 464 00000434 08870000                     bclr    #0,d7
 465 00000438 21470010                     move.l  d7,Stack(a0)
 466 0000043C 227900000030                 move.l  basepg,a1
 467 00000442 22E80004                     move.l  LoAdr(a0),(a1)+
 468 00000446 22E80008                     move.l  HiAdr(a0),(a1)+
 469 0000044A 22F900000024                 move.l  cseg,(a1)+
 470 00000450 22F900000002                 move.l  csize,(a1)+
 471 00000456 22F900000028                 move.l  dseg,(a1)+
 472 0000045C 22F900000006                 move.l  dsize,(a1)+
 473 00000462 22F90000002C                 move.l  bseg,(a1)+
 474 00000468 22B90000000A                 move.l  bsize,(a1)
 475                               * find size of free memory after bss segment
 476 0000046E 2E280008                     move.l  HiAdr(a0),d7    * d7 contains next segment above bss
 477 00000472 2C29FFFC                     move.l  -4(a1),d6
 478 00000476 DC99                         add.l   (a1)+,d6        * d6 points to start of free mem after bss
 479 00000478 2C7C00000024                 movea.l #cseg,a6        * a6 points to segment to try
 480 0000047E 7A04                         moveq   #4,d5           * try for all segments
 481 00000480 42B90000002C                 clr.l   bseg            *    but force bss not to appear
 482 00000486 BC96                 setb1:  cmp.l   (a6),d6         * segment above bss?
 483 00000488 6206                         bhi     setb2
 484 0000048A BE96                         cmp.l   (a6),d7         * segment is above bss. Is it below previous?
 485 0000048C 6302                         bls     setb2
 486 0000048E 2E16                         move.l  (a6),d7
 487 00000490 4A9E                 setb2:  tst.l   (a6)+           * point to next segment
 488 00000492 51CDFFF2                     dbf     d5,setb1
 489 00000496 9E86                         sub.l   d6,d7           * diff between bss top and next segment abv
 490 00000498 22C7                         move.l  d7,(a1)+
 491                               *                       now put disk number that we loaded from into base page
 492 0000049A 24680000                     movea.l FCBPtr(a0),a2
 493 0000049E 1012                         move.b  (a2),d0         * get disk select byte
 494 000004A0 6606                         bne     setb3           * if not auto-select, skip
 495 000004A2 7019                         move    #25,d0
C P / M   6 8 0 0 0   A s s e m b l e r		Revision 02.03		Page  10
Source File: pgmld.s

 496 000004A4 4E42                         trap    #2              * get default disk
 497 000004A6 5240                         addq    #1,d0           * we want it in range of 1..16
 498 000004A8 12C0                 setb3:  move.b  d0,(a1)+        * move disk number into base page
 499 000004AA 4280                         clr.l   d0              * function OK
 500 000004AC 4E75                         rts
 501                               
 502                               
 503 00000000                              .bss
 504                               
 505                               * offsets from start of parameter block
 506                               FCBPtr  = 0
 507                               LoAdr   = 4
 508                               HiAdr   = 8
 509                               BasPage = 12            * return parameters
 510                               Stack   = 16
 511                               Flags   = 21
 512                               
 513                               hdr:
 514                                                               * load file header is read into here
 515 00000000                      magic:          .ds.w   1
 516 00000002                      csize:          .ds.l   1
 517 00000006                      dsize:          .ds.l   1
 518 0000000A                      bsize:          .ds.l   1
 519 0000000E                      bpsize:         .ds.l   1       * symb tbl size is swapped with base page size
 520 00000012                      stksize:        .ds.l   1
 521 00000016                      tstart:         .ds.l   1
 522 0000001A                      rlbflg:         .ds.w   1
 523 0000001C                      dstart:         .ds.l   1
 524 00000020                      bstart:         .ds.l   1
 525                               
 526 00000024                      cseg:           .ds.l   1
 527 00000028                      dseg:           .ds.l   1
 528 0000002C                      bseg:           .ds.l   1
 529 00000030                      basepg:         .ds.l   1
 530 00000034                      stk:            .ds.l   1
 531                               
 532 00000038                      symsize:        .ds.l   1
 533 0000003C                      temp:           .ds.l   1
 534 00000040                      loop:           .ds.w   1
 535 00000042                      bufbyts:        .ds.w   1
 536                               
 537 00000044                              .end
C P / M   6 8 0 0 0   A s s e m b l e r		Revision 02.03		Page  11
Source File: pgmld.s

S y m b o l   T a b l e

BasPage   0000000C ABS   FCBPtr    00000000 ABS   Flags     00000015 ABS   HiAdr     00000008 ABS   
LoAdr     00000004 ABS   Stack     00000010 ABS   _pgmld    00000000 TEXT  badadr    0000024A TEXT  
badhdr    00000080 TEXT  basepg    00000030 BSS   bpsize    0000000E BSS   bseg      0000002C BSS   
bsize     0000000A BSS   bstart    00000020 BSS   bufbyts   00000042 BSS   chk1      000000E4 TEXT  
chksegs   000000C4 TEXT  conf1     000000A8 TEXT  confbd    000000B6 TEXT  confgd    000000B8 TEXT  
conflict  00000084 TEXT  cseg      00000024 BSS   csize     00000002 BSS   dseg      00000028 BSS   
dsize     00000006 BSS   dstart    0000001C BSS   finrd     00000308 TEXT  fnd1      000000FE TEXT  
fndseg    000000F0 TEXT  geth1     00000078 TEXT  gethdr    00000060 TEXT  hdr       00000000 BSS   
lddone    0000003A TEXT  loop      00000040 BSS   magic     00000000 BSS   moveb1    0000026A TEXT  
moveb2    0000026C TEXT  movebuf   0000024E TEXT  noreloc   00000032 TEXT  rdbad     00000332 TEXT  
rdtxt     00000272 TEXT  rdtxt1    0000027E TEXT  rdtxt2    00000294 TEXT  rdtxt3    000002AE TEXT  
rdtxt4    000002C0 TEXT  rdtxt5    000002CA TEXT  rdtxt6    000002E6 TEXT  rdtxt7    0000032A TEXT  
rdtxt8    00000330 TEXT  readseq   00000046 TEXT  relabs    00000358 TEXT  relbad    00000352 TEXT  
relbss    00000368 TEXT  relc1     00000376 TEXT  relcode   00000368 TEXT  reldata   00000368 TEXT  
rellong   00000360 TEXT  reloc     00000380 TEXT  reloc1    000003E2 TEXT  reloc2    000003E8 TEXT  
reloc3    00000400 TEXT  reloc4    00000406 TEXT  relocwor  00000336 TEXT  relop     00000358 TEXT  
rlbflg    0000001A BSS   secsize   00000080 ABS   set0      0000014E TEXT  set1      0000016C TEXT  
set2      000001AC TEXT  set3      000001CC TEXT  set4      000001F6 TEXT  set5      0000020A TEXT  
set6      0000021E TEXT  set7      0000022E TEXT  seta      00000160 TEXT  setaddr   0000011A TEXT  
setb1     00000486 TEXT  setb2     00000490 TEXT  setb3     000004A8 TEXT  setdma    00000056 TEXT  
setrtn    00000420 TEXT  skip1     000003A8 TEXT  skip2     000003B8 TEXT  skip3     000003C2 TEXT  
sldhi     0000018A TEXT  stk       00000034 BSS   stksize   00000012 BSS   symsize   00000038 BSS   
temp      0000003C BSS   trymemtp  000000BA TEXT  tstart    00000016 BSS   