What happens when main() returns on ARM-GCC
The main is just like any other function. The project has custom statup code and what it does after returning from main depends on with what defines it was compiled with. One option is that it remains in an infinite loop so it halts. Another option is that the return value is an address of function to execute. Startup code for my ARM just resets the MCU so it restarts.
UPD(by Skobls): The custom startup code resides in /crt0_gnu.S file. Here is the interesting part (condensed version):
/* Branch on C code Main function (with interworking) */
_branch_main:
    ldr     r4, = main
    mov     lr, pc
    bx      r4

    mov     lr, pc
    bx      r0

The first block is a standard construct. The bx r4 instruction makes the CPU jump to the main() function. When the latter returns, by Procedure Call Standard for the ARM® Architecture it stores its result in the r0 register. Thus, the bx r0 instruction makes an indirect jump to whatever address main() had returned. In particular, the NULL return value from main() will restart the AT91 Bootstrap without fully resetting the CPU and without executing the 1st-Level Bootloader from the CPU ROM