NetBSD/x68k 1.6 のブートストラップ解説コーナー。
$Id: exec_image.S.html,v 1.9 2002/12/23 06:01:17 isaki Exp $

/*	$NetBSD: exec_image.S,v 1.2 2001/09/27 14:08:28 minoura Exp $	*/

/*
 * Copyright (c) 2001 Minoura Makoto.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include <machine/asm.h>

#ifndef LASTADDR
#define LASTADDR	(0x00ed0008)
#endif

	.text
	.even

ENTRY_NOPROFILE(exec_image)
||	void exec_image(loaded,executed,entry,size,bootdev,boothowto)
|| 	unsigned int loaded;
||	unsigned int executed;
||	unsigned int entry;
||	int size;
||	int bootdev;
||	int boothowto;
	| 帰る先のアドレスはいらないので捨てる。
	addl		#4,%sp			| throw away the return address
	| 引数を取り出す。
	| %a4: u_int loaded
	| %a5: u_int executed
	| %a6: u_int entry
	| %d5: int   size
	| %d6: int   bootdev
	| %d7: int   boothowto
	moveml		%sp@+,%a4-%a6
	moveml		%sp@+,%d5-%d7

/* copy the trampoline to the last physical page. */
/* trampoline ルーチンを物理メモリの最後のページにコピーする */
	|
	| スタックポインタを物理メモリの最終番地にする。物理メモリの最終番地は
	| SRAM に記録してある「メインメモリ容量」をそのまま使用する。
	| Human68k ではこの欄はあまり意味をもたなかったはずだが、NetBSD/x68k
	| ではこのような使われ方をしているため正しく指定しないといけない。
	| 実搭載メモリよりも大きい値を指定していると、この次の lea で
	| お亡くなりになる。実搭載メモリより少ない値を指定する分にはそれだけ
	| メモリの少ない状況をエミュレートできるだけで実害はない。
	| (といっても普段(メモリ12MB)の環境を急に 4MB で起動するとスラッシング
	| になってしまい1時間経ってもログインプロンプトに辿り着けずリセット
	| したくなる状況ではある...)
	moval		LASTADDR,%sp		| tmpstack from end of physmem
	| %a3 をそのスタックポインタから 4096 バイト手前に設定。
	| %a3 はこの後 trampoline の転送先アドレスとして使われるので、
	| つまり最後の1ページを使用するということになる。
	lea		%sp@(-4096),%a3		| use last phys page as tramp

	| memcpy(%a3, trampoline, sizeof(trampoline));
	| C の memcpy は /boot (自分自身) の中にあるのでまだ使える。
	movl		#(end_trampoline-trampoline),%sp@-
	pea		%pc@(trampoline)
	pea		%a3@
	jbsr		_C_LABEL(memcpy)	| memcpy() is still alive
	| スタックを元に戻す、必要はあるのか?
	lea		%sp@(12),%sp

	| 転送した先の trampoline へジャンプ。
	jmp		%a3@			| jump to tramp

ASENTRY_NOPROFILE(trampoline)
||	%a4:	loaded
||	%a5:	executed
||	%a6:	entry
||	%d5:	size
||	%d6:	bootdev
||	%d7:	boothowto
	| 何かをスタックに積んでおく。何だろ。
	movl		%d5,%sp@-		| push last arg (esym)
	movel		LASTADDR,%sp@-		| second arg (physsize)
	pea		%a5@			| first arg (firstpa)

	| %a4 が現在カーネルが読み込んである先頭番地。
	| %a5 が実際にカーネルをおく先頭番地。
	| なのでこれらが一緒ならコピーは不要。
	cmpl		%a4,%a5			| if (l == x)
	beq		L1			|	copy not required

/* this may overwrite the trap vectors; disable interrupt. */
/*
 * これから行なうカーネルのコピーはトラップベクタも書き換えるので、
 * その前に割り込みを禁止しておく。
 */
	| %sr の上位バイトはシステムバイトでこんな感じ。
	| $27 はスーパバイザモードで許可する割り込みレベルを最高にする。
	| +----------------------------------+
	| | T |   | S |   |   | I2 | I1 | I0 |
	| +----------------------------------+
	|
	oriw		#0x2700,%sr

	| カーネルをコピーする。さっき使った memcpy はこれから書き換える
	| /boot の中にあるのでもう使えない。自力でコピーする。
L0:	movb		%a4@+,%a5@+		| copy kern to x
	subql		#1,%d5
	bne		L0

L1:
	| 使ってないレジスタは全部クリアするらしい。
	| %d6, %d7 にはパラメータが入っているのでクリアしない。
	movq		#0,%d0			| reg arg (unused)
	movq		#0,%d1			| reg arg (unused)
	movq		#0,%d2			| reg arg (unused)
	movq		#0,%d3			| reg arg (unused)
	movq		#0,%d4			| reg arg (unused)
	movq		#0,%d5			| reg arg (unused)
						| bootdev(%d6) is already set
						| boothowto(%d7) is already set
	| エントリアドレスが %a6 に入っているので %a0 に移しておいて
	| 他を全部クリア。
	| 最後に %vbr をクリアする。って %vbr って何?
	moval		%a6,%a0			| entry
	moval		%d0,%a1			| reg arg (unused)
	moval		%d0,%a2			| reg arg (unused)
	moval		%d0,%a3			| reg arg (unused)
	moval		%d0,%a4			| reg arg (unused)
	moval		%d0,%a5			| reg arg (unused)
	moval		%d0,%a6			| reg arg (unused)
	movec		%a1,%vbr		| clear vbr

	| カーネルへジャーンプ!
	jsr		%a0@			| here we go!

/*
 * ここまでを高位番地へ転送するので、
 * end_trampoline はそのサイズを知るためのラベル。
 */
	/* NOTREACHED */
end_trampoline:

井崎のホームページへ戻る
isaki@NetBSD.org / isaki@x68k.net