atexit.s 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. |atexit function copyright (C) 2002, Kevin Kofler
  2. |requires new exit support (__save__sp__)
  3. |Many thanks to Patrick Pélissier and Stephan Effelsberg for ideas on how to
  4. |implement this. Stephan Effelsberg's C implementation inspired this mostly,
  5. |but I have changed it so that exit and atexit will not be included if not
  6. |used. There is only a small 20-byte exit support needed.
  7. .xdef atexit
  8. | This file requires the startup exit support.
  9. .xdef __ref_all___save_all_registers_main
  10. .text
  11. .equ __malloc,0xa2 /* HeapAllocPtr */
  12. .equ __free,0xa3 /* HeapFreePtr */
  13. .equ __num_regs,10 |number of registers saved by the exit support
  14. atexit:
  15. |find the return address:
  16. movea.l __save__sp__:l,%a0 |stack pointer before restoring the registers
  17. |(NOT PC-relative because of programs >32 KB)
  18. |The return address is now at (a0).
  19. |check if the return address is .L__atexit__new__return
  20. cmpi.l #.L__atexit__new__return:l,(%a0)
  21. beq.s .L__atexit__return__address__ok |if it is, skip ahead
  22. |Else:
  23. |- move the current return address to .L__atexit__return+2
  24. move.l (%a0),.L__atexit__return+2
  25. |- change the return address to .L__atexit__new__return
  26. move.l #.L__atexit__new__return:l,(%a0)
  27. clr.l .L__atexit__num__funcs |initialize the number of atexit functions to 0
  28. |allocate a handle for the functions
  29. pea.l 4:w
  30. movea.l 0xc8,%a0
  31. move.l (__malloc*4,%a0),%a0
  32. jsr (%a0) |a0=malloc(4);
  33. addq.l #4,%a7
  34. bra.s .L__atexit__handle__allocated
  35. .L__atexit__return__address__ok:
  36. |reallocate the handle for the functions
  37. move.l (.L__atexit__num__funcs,%PC),%d0
  38. lsl.l #2,%d0
  39. addq.l #4,%d0
  40. move.l (.L__atexit__ptr__funcs,%PC),%a0
  41. jbsr realloc |a0=realloc(.L__atexit__ptr__funcs,.L__atexit__num__funcs*4+4);
  42. .L__atexit__handle__allocated:
  43. |If a0 is NULL, there was not enough memory, so we return an error code.
  44. moveq #0,%d0
  45. cmpa.l %d0,%a0 |if (!a0)
  46. seq.b %d0
  47. beq.s .L__atexit__rts |return 255;
  48. move.l %a0,.L__atexit__ptr__funcs |save a0 to .L__atexit__ptr__funcs
  49. |Now we store the function given as an argument into the allocated memory.
  50. move.l (.L__atexit__num__funcs,%PC),%d1
  51. lsl.l #2,%d1
  52. move.l (4,%a7),(0,%a0,%d1:l) |.L__atexit__ptr__funcs[.L__atexit__num__funcs]=4(a7);
  53. |And there is 1 more atexit function now:
  54. addq.l #1,.L__atexit__num__funcs
  55. .L__atexit__rts:
  56. rts
  57. |This will be executed when the _main function or the exit function tries to
  58. |return:
  59. .L__atexit__new__return:
  60. move.l (.L__atexit__num__funcs,%PC),%d0 |if there are no functions to call, return
  61. beq.s .L__atexit__no__funcs |immediately
  62. | movem.l %a2/%a5/%d3,-(%a7)
  63. |no need to save and restore the registers, the exit support will do it for us
  64. movea.l 0xc8,%a5
  65. movea.l (.L__atexit__ptr__funcs,%PC),%a2
  66. move.l %d0,%d3 |save d0 to d3
  67. lsl.l #2,%d0 |point a2 to the address of the last function + 4
  68. add.l %d0,%a2 |that is, .L__atexit__ptr__funcs[.L__atexit__num__funcs]
  69. subq.l #1,%d3 |subtract 1 from the number of functions for the dbra loop
  70. |call all atexit functions now
  71. .L__atexit__loop:
  72. movea.l -(%a2),%a0
  73. jsr (%a0)
  74. dbra.w %d3,.L__atexit__loop
  75. |a2 now points to the beginning of the allocated memory for the pointers
  76. |free this memory
  77. pea.l (%a2)
  78. move.l (__free*4,%a5),%a0
  79. jsr (%a0) |free(.L__atexit__ptr__funcs);
  80. addq.l #4,%a7
  81. | movem.l (%a7)+,%a2/%a5/%d3
  82. |no need to save and restore the registers, the exit support will do it for us
  83. .L__atexit__no__funcs:
  84. |This will return to the actual return address (which will be patched in
  85. |instead of the 0 by the first call to atexit).
  86. .L__atexit__return: jmp.l 0:l
  87. |data:
  88. .L__atexit__ptr__funcs: .long 0 |pointer to the atexit functions
  89. .L__atexit__num__funcs: .long 0 |number of atexit functions