; loaderasm.s - provides all assembler routines needed by loader.c
; by Steven Reiz 15/1/89 - 18/3/89
; bugs: movek puts the stack (top) at $080000 so you must have ram below it
; and it must not be used for the kernel.
; movek puts the address of the transdat (transfer data) at 0 (where the
; autovectors etc. are), this will certainly cause problems when
; you try to run the loader on an amiga with an mmu...
; as if that ain't enough it puts $080000 at 4 ($00000004) so all minix tasks
; can 'allocate' memory by decreasing it (mm reads and allocates it)

; run_movek - run the mlroutine in transdat
; run_movek(transdat)
; long transdat; {
    public  _run_movek
_run_movek:
    move.l  4(sp),a5            ; so the mlroutine (movek) can use it
    jmp     16(a5)              ; jump into the transdat to mlroutine


; movek - this routine is the mlroutine in transdat, the struct transferdata
; used to transfer data from the loader to the minix kernel,
; it expects transdat in a5, it reads the kernel addresses and size from
; it, then it copies the kernel from its load to its run address,
; it puts transdat on the stack, then it reads runaddress from transdat
; and jumps to it.
    public  _movek_start
    public  _movek_end
_movek_start:
    move.l  #$080000,sp         ; so the stack won't collide with the kernel
    move.l  0(a5),a0            ; NOW a0 is kernel source address
    move.l  4(a5),a1            ; NOW a1 is kernel destination address
    move.l  12(a5),d1           ; kernel size in bytes
    add.l   #3,d1               ; we're going to round it up to the next 4 bytes
    and.l   #$fffffffc,d1       ; NOW d1 is kernel size in rounded bytes
    move.l  d1,d0
    lsr.l   #2,d0               ; NOW d0 is kernel size in longs
    cmp.l   a0,a1               ; test if we should copy up or down
    beq     movek_ok            ; hey, a miracle !
    blt     movek_up            ; dest<src so copy upwards
movek_down:                     ; dest>src so copy downwards
    add.l   d1,a0
    add.l   d1,a1               ; downwards so starting at the end
mk_down_loop:
    move.l  -(a0),-(a1)
    subq.l  #1,d0               ; copy d0 longs
    bne     mk_down_loop
    bra     movek_ok
movek_up:
mk_up_loop:                     ; upwards so starting at the begin
    move.l  (a0)+,(a1)+
    subq.l  #1,d0
    bne     mk_up_loop
movek_ok:                       ; kernel copied
    move.l  a5,$0000            ; address of transdat at 0 for minix to find
    move.l  #$080000,$0004      ; end of piece of mem at 4 for minix to find
    move.l  8(a5),a0            ; the kernel runaddress
    jmp     (a0)                ; there she goes, kernel started !!!
_movek_end:
    end
