home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 351.lha / ontrap / c.a < prev    next >
Text File  |  1990-02-28  |  11KB  |  435 lines

  1. *
  2. * C initial startup procedure under AmigaDOS
  3. * Use the following command line to make c.o
  4. * asm -u -iINCLUDE: c.a
  5. *
  6. * Use the following command line to make cres.o
  7. * asm -u -dRESIDENT -iINCLUDE: -ocres.o c.a
  8. *
  9.     INCLUDE    "exec/types.i"
  10.     INCLUDE    "exec/alerts.i"
  11.     INCLUDE    "exec/nodes.i"
  12.     INCLUDE    "exec/lists.i"
  13.     INCLUDE    "exec/ports.i"
  14.     INCLUDE    "exec/libraries.i"
  15.     INCLUDE    "exec/tasks.i"
  16.     INCLUDE    "exec/memory.i"
  17.     INCLUDE    "exec/execbase.i"
  18.     INCLUDE    "libraries/dos.i"
  19.     INCLUDE    "libraries/dosextens.i"
  20.     INCLUDE    "workbench/startup.i"
  21.     INCLUDE    "exec/funcdef.i"
  22.     INCLUDE    "exec/exec_lib.i"
  23.     INCLUDE    "libraries/dos_lib.i"
  24.  
  25. MEMFLAGS    EQU    MEMF_CLEAR+MEMF_PUBLIC
  26. AbsExecBase    EQU    4
  27.  
  28. ; some usefull macros:
  29.  
  30. callsys macro
  31.     CALLLIB _LVO\1
  32.     endm
  33.     
  34.     xdef    XCEXIT        * exit(code) is standard way to leave C.
  35.     xdef    @XCEXIT
  36.     
  37.     xref    LinkerDB    * linker defined base value
  38.     xref    _BSSBAS        * linker defined base of BSS
  39.     xref    _BSSLEN        * linker defined length of BSS
  40.     IFD    RESIDENT
  41.     xref    RESLEN
  42.     xref    RESBASE
  43.     xref    NEWDATAL
  44.     xref    _stack
  45.     ENDC
  46.     
  47. *       library references
  48.  
  49.     section text,code
  50.  
  51.     xref    _main            * Name of C program to start with.
  52.     xref    MemCleanup        * Free all allocated memory
  53.     xref    __fpinit        * initialize floating point
  54.     xref    __fpterm        * terminate floating point
  55.     
  56. start:
  57.     movem.l d1-d6/a0-a6,-(a7)
  58.  
  59.     move.l  a0,a2            * save command pointer
  60.     move.l  d0,d2            * and command length
  61.     lea     LinkerDB,a4        * load base register
  62.     move.l  AbsExecBase.W,a6
  63.  
  64.     IFND    RESIDENT
  65.     lea     _BSSBAS,a3        * get base of BSS
  66.     moveq   #0,d1
  67.     move.l  #_BSSLEN,d0        * get length of BSS in longwords
  68.     bra.s   clr_lp            * and clear for length given
  69. clr_bss move.l  d1,(a3)+
  70. clr_lp  dbf     d0,clr_bss
  71.     move.l  a7,_StackPtr(A4)       * Save stack ptr
  72.     move.l  a6,SysBase(A4)
  73.     ENDC
  74.     
  75.  
  76.     IFD    RESIDENT
  77.     movem.l    d2,-(a7)
  78.     movem.l a0-a2,-(a7)
  79.  
  80. *------ get the size of the stack, if CLI use cli_DefaultStack
  81. *------                       if WB use a7 - TC_SPLOWER
  82.     move.l    ThisTask(a6),A3
  83.     move.l  pr_CLI(A3),d1
  84.     beq.s   fromwb
  85.     lsl.l    #2,d1
  86.     move.l    d1,a0
  87.     move.l    cli_DefaultStack(a0),d1
  88.     lsl.l    #2,d1            * # longwords -> # bytes
  89.     bra.s    dostack
  90.  
  91. fromwb:
  92.     move.l    a7,d1             
  93.     sub.l    TC_SPLOWER(a3),d1     
  94. dostack:
  95.     moveq    #0,d2            * use d2 as flag for newstack or not
  96.     move.l    #RESLEN,d0
  97.     cmp.l    _stack(a4),d1        * This a4 is in the original 
  98.                     * set of data
  99.     bcc.s    nochange    
  100.     move.l    _stack(a4),d1
  101.     add.l    d1,d0            * increase size of mem for new stack
  102.     moveq    #1,d2            * set flag
  103.         
  104. nochange:
  105.     move.l    d1,a3            * save stacksize to set up stack checking
  106.     move.l    #MEMFLAGS,d1
  107.     callsys AllocMem
  108.     tst.l    d0
  109.     bne.s    ok1
  110.     movem.l    (a7)+,d2/a0-a2
  111.     rts
  112.  
  113. ok1:    move.l    d0,a0
  114.     move.l    d0,a2
  115.  
  116. ;a2 now has difference
  117.     move.l    d0,a1
  118.     move.l    #NEWDATAL,d0
  119.     sub.l    #RESBASE,a4
  120. ;copy data over
  121. cpy:    move.l    (a4)+,(a0)+
  122.     subq.l    #1,d0
  123.     bne.s    cpy
  124. ;a4 now points at number of relocs
  125.     move.l    (a4)+,d0
  126. reloc:  beq.s    nreloc
  127.     move.l    a1,a0
  128.     add.l    (a4)+,a0        * a0 now has add of reloc
  129.     add.l    (a0),a2
  130.     move.l    a2,(a0) 
  131.     move.l    a1,a2            * restore offset
  132.     subq.l    #1,d0
  133.     bra.s    reloc
  134.     
  135. nreloc: move.l    a1,a4            * set up new base register
  136.     add.l    #RESBASE,a4
  137.  
  138.     move.l    #RESLEN,realdatasize(a4)
  139.     movem.l (a7)+,a0-a2
  140.  
  141.     move.l  a6,SysBase(A4)
  142.     tst.b    d2
  143.     movem.l    (a7)+,d2        * restore d2 
  144.     movem.l a7,_StackPtr(A4)    * Save stack ptr (movem doesn't
  145.                     * change flags
  146.     beq.s    nochg2
  147.  
  148. *------ set up new stack
  149.     move.l    a4,d0
  150.     sub.l    #RESBASE,d0
  151.     add.l    #RESLEN,d0
  152.     add.l    _stack(a4),d0        * here a4 will be pointing at the
  153.                     * new data, but _stack will be the
  154.                     * same if all goes well
  155.                     
  156.     sub.l    #128,d0            * 128 down for good measure
  157.     move.l    d0,a7
  158.     move.l    _stack(a4),d0
  159.     move.l    d0,4(a7)        * fill in size of new stack    
  160.     add.l    d0,realdatasize(a4)     * need to know how much to free later
  161.  
  162. nochg2:
  163. *------ Set _base for stack checking
  164.     move.l    a7,d1
  165.     sub.l    a3,d1            * get top of stack
  166.     add.l   #128,D1            * allow for parms overflow
  167.     move.l  D1,_base(A4)        * save for stack checking
  168.  
  169.     ENDC
  170.  
  171. clrwb:
  172.     clr.l   WBenchMsg(A4)
  173.  
  174. *JVP--- get the address of our task
  175.     move.l    ThisTask(a6),A3
  176.  
  177. *JVP--- set up for my very own trap handler
  178.     move.l    TC_TRAPCODE(a3),oldTrapCode(a4)    * save the old trap code
  179.     lea    trapcode,a0        * do something a little less
  180.     move.l    a0,TC_TRAPCODE(a3)    * drastic.
  181.  
  182. *-----  clear any pending signals
  183.     moveq    #0,d0
  184.     move.l    #$00003000,d1
  185.     callsys    SetSignal
  186.     
  187.  
  188. *------ attempt to open DOS library:
  189.     lea     DOSName(PC),A1
  190.     moveq.l #0,D0
  191.     callsys OpenLibrary
  192.     move.l  D0,DOSBase(A4)
  193.     bne.s    ok2
  194.     moveq.l #100,d0
  195.     bra.w   exit2
  196.  
  197. ok2:
  198. *------ are we running as a son of Workbench?
  199.     move.l    ThisTask(a6),A3
  200.     move.l  pr_CurrentDir(A3),curdir(A4)
  201.     tst.l   pr_CLI(A3)
  202.     beq.s  fromWorkbench
  203.     
  204. *=======================================================================
  205. *====== CLI Startup Code ===============================================
  206. *=======================================================================
  207. *
  208. * Entry: D2 = command length
  209. *    A2 = Command pointer
  210. fromCLI:
  211.     ifnd    RESIDENT    * we need to set _base if not resident
  212.         move.l  a7,D0           * get top of stack
  213.         sub.l   4(a7),D0        * compute bottom 
  214.         add.l   #128,D0         * allow for parms overflow
  215.         move.l  D0,_base(A4)    * save for stack checking
  216.     endc
  217.     
  218. *------ find command name:
  219.     move.l  pr_CLI(a3),a0
  220.     add.l   a0,a0       * bcpl pointer conversion
  221.     add.l   a0,a0
  222.     move.l  cli_CommandName(a0),a1
  223.     add.l   a1,a1       * bcpl pointer conversion
  224.     add.l   a1,a1
  225.  
  226. *------ collect parameters:
  227.     move.l  d2,d0           * get command line length
  228.     moveq.l #0,d1
  229.     move.b  (a1)+,d1
  230.     move.l  a1,_ProgramName(A4)
  231.     add.l   d1,d0           * add length of command name
  232.     addq.l  #1,d0           * allow for space after command 
  233.  
  234.     clr.w   -(A7)           * set null terminator for command line
  235.     addq.l  #1,D0           * force to even number of bytes
  236.     andi.w  #$fffe,D0           *(round up)
  237.     sub.l   D0,A7           * make room on stack for command line
  238.     subq.l  #2,D0
  239.     clr.w   0(A7,D0)
  240.  
  241. *------ copy command line onto stack
  242.     move.l  d2,d0           * get command line length
  243.     subq.l  #1,d0
  244.     add.l   d1,d2
  245.  
  246. copy_line:
  247.     move.b  0(A2,D0.W),0(A7,D2.W)   * copy command line to stack
  248.     subq.l  #1,d2
  249.     dbf     d0,copy_line
  250.     move.b  #' ',0(a7,d2.w)     * add space between command and parms
  251.     subq.l  #1,d2
  252.  
  253. copy_cmd:
  254.     move.b  0(a1,d2.w),0(a7,d2.w)   * copy command name to stack
  255.     dbf     d2,copy_cmd
  256.     move.l  A7,A1
  257.     move.l  A1,-(A7)        * push command line address
  258.     bra.s   main            * call C entrypoint
  259.  
  260. *=======================================================================
  261. *====== Workbench Startup Code =========================================
  262. *=======================================================================
  263.  
  264. fromWorkbench:
  265.  
  266.     ifnd    RESIDENT    * we need to set _base if not resident
  267.         move.l  TC_SPLOWER(a3),_base(A4) * set base of stack
  268.     moveq   #127,d0
  269.     addq.l    #1,d0                    * Efficient way of getting in 128
  270.         add.l   d0,_base(A4)             * allow for parms overflow
  271.     endc
  272.  
  273. *------ we are now set up.  wait for a message from our starter
  274.     lea     pr_MsgPort(A3),a0       * our process base
  275.     callsys WaitPort
  276.     lea     pr_MsgPort(A3),a0       * our process base
  277.     callsys GetMsg
  278.     move.l  d0,WBenchMsg(a4)
  279.     move.l  d0,-(SP)
  280. *
  281.     move.l  d0,a2           * get first argument
  282.     move.l  sm_ArgList(a2),d0
  283.     beq.s   do_cons
  284.     move.l  DOSBase(a4),a6
  285.     move.l  d0,a0
  286.     move.l  wa_Lock(a0),d1
  287.     move.l  d1,curdir(A4)
  288.     callsys CurrentDir
  289. do_cons:
  290.     move.l  sm_ToolWindow(a2),d1    * get the window argument
  291.     beq.s   do_main
  292.     move.l  #MODE_OLDFILE,d2
  293.     callsys Open
  294.     move.l  d0,stdin(a4)
  295.     beq.s   do_main
  296.     lsl.l   #2,d0
  297.     move.l  d0,a0
  298.     move.l  fh_Type(a0),pr_ConsoleTask(A3)
  299. do_main:
  300.     move.l  WBenchMsg(A4),a0    * get address of workbench message
  301.     move.l  a0,-(a7)        * push argv
  302.     pea     NULL(a4)        * push argc
  303.     move.l  sm_ArgList(a0),a0       * get address of arguments
  304.     move.l  wa_Name(a0),_ProgramName(A4)       * get name of program
  305.  
  306. *=============================================
  307. *------ common code --------
  308. *=============================================
  309.  
  310. main    jsr     __fpinit(PC)        * Initialize floating point
  311.     jsr     _main(PC)           * call C entrypoint
  312.     moveq.l #0,d0           * set successful status
  313.     bra.s   exit2
  314. *
  315.  
  316. XCEXIT:
  317.     move.l  4(SP),d0        * extract return code
  318. @XCEXIT:
  319. exit2:
  320.     move.l  d0,-(a7)
  321.     move.l  _ONEXIT(A4),d0      * exit trap function?
  322.     beq.s   exit3
  323.     move.l  d0,a0
  324.     jsr     (a0)
  325. exit3   jsr     MemCleanup(PC)      * cleanup leftover memory alloc.
  326.     move.l  AbsExecBase.W,a6
  327.     move.l  DOSBase(A4),a1
  328.     callsys CloseLibrary        * close Dos library
  329.  
  330.     jsr     __fpterm(PC)        * clean up any floating point
  331.  
  332. done_1c:
  333. *------ if we ran from CLI, skip workbench cleanup:
  334.     tst.l   WBenchMsg(A4)
  335.     beq.s   exitToDOS
  336.     move.l  stdin(a4),d1
  337.     beq.s   done_4
  338.     callsys Close
  339. done_4:
  340.  
  341. *------ return the startup message to our parent
  342. *       we forbid so workbench can't UnLoadSeg() us
  343. *       before we are done:
  344.     move.l  AbsExecBase.W,A6
  345.     callsys Forbid
  346.     move.l  WBenchMsg(a4),a1
  347.     callsys ReplyMsg
  348.  
  349. *------ this rts sends us back to DOS:
  350. exitToDOS:
  351. *JVP--- restore original TC_TRAPCODE leaving the shell as it was.
  352.     move.l    ThisTask(a6),a1
  353.     move.l    oldTrapCode(a4),TC_TRAPCODE(a1)    * politely restore this guy.
  354.     IFD    RESIDENT
  355.     move.l    realdatasize(a4),d0
  356.     move.l  a4,a1
  357.     sub.l   #RESBASE,a1
  358.     move.l  AbsExecBase.W,a6
  359.         move.l  (A7)+,d6
  360.         movea.l _StackPtr(a4),a5
  361.     callsys FreeMem
  362.         move.l   d6,d0
  363.         movea.l  a5,sp
  364.         ELSE
  365.     move.l  (A7)+,D0
  366.     movea.l _StackPtr(a4),SP    * restore stack ptr
  367.     ENDC
  368.     
  369.     movem.l (a7)+,d1-d6/a0-a6
  370.     rts
  371.  
  372. *JVP---------------------------------------------------------------------
  373. *  Trap handler. Helps avoid the GURU.
  374.  
  375. trapcode:
  376.         move.l    (sp)+,d0    ; get the trap code off the supervisor stack
  377.                 andi    #$DFFF,SR    ; switch back to Usermode
  378.                 lea     LinkerDB,A4    ; load linker defined base register
  379.                 move.l    d0,_TRAPCODE(A4) ; Make the trap code available to C functions
  380.         move.l    _ONTRAP(A4),d0    ; get the new trap vector
  381.         beq    1$        ; skip C routine call if not supplied
  382.         move.l    d0,a0        ; make it a funtion address
  383.                 jsr     (a0)        ; Let C code clean up.
  384. 1$:        move.l    _TRAPCODE(A4),d0    ; use the trap code as the return code
  385.         add.l    #1000,d0    ; give it an offset to force exit message
  386.                 jmp     exit2        ; exit this error prone program.
  387.  
  388.  
  389. DOSName     dc.b    'dos.library',0
  390.  
  391.     section __MERGED,BSS
  392. *
  393.     xref    DOSBase
  394.  
  395.     xdef    NULL,SysBase,WBenchMsg
  396.     xdef    curdir,_mbase,_mnext,_msize,_tsize
  397.     xdef    _oserr,_OSERR,_FPERR,_SIGFPE,_ONERR,_ONEXIT,_ONBREAK
  398.     xdef    _SIGINT
  399.     xdef    _ProgramName,_StackPtr,_base
  400.  
  401. *JVP--- ontrap externals
  402.     xdef    _ONTRAP,_TRAPCODE
  403. *
  404.     ifd    RESIDENT
  405. realdatasize    ds.b    4    * size of memory allocated for data +
  406.                 * possible stack
  407.     endc
  408.     
  409. NULL        ds.b    4    *
  410. _base        ds.b    4    * base of stack
  411. _mbase        ds.b    4    * base of memory pool
  412. _mnext        ds.b    4    * next available memory location
  413. _msize        ds.b    4    * size of memory pool
  414. _tsize        ds.b    4    * total size?
  415. _oserr        equ     *
  416. _OSERR        ds.b    4
  417. _FPERR        ds.b    4
  418. _SIGFPE        ds.b    4
  419. _SIGINT        ds.b    4
  420. _ONERR        ds.b    4
  421. _ONEXIT        ds.b    4
  422. _ONBREAK    ds.b    4
  423. curdir         ds.b    4
  424. SysBase        ds.b    4
  425. WBenchMsg    ds.b    4
  426. _StackPtr    ds.b    4
  427. stdin        ds.b    4
  428. _ProgramName    ds.b    4
  429. *JVP--- ontrap storage
  430. _ONTRAP         ds.b    4        * my trap handler vector
  431. _TRAPCODE    ds.b    4
  432. oldTrapCode     ds.b    4
  433.         END
  434.