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