MIPSエミュレータspim にはシステムコールが幾つか定義されています。 しかしシステムコール自体の実現はspim実装ソースコードで行なわれています (C言語による実装で, ハードコードされている)。 すなわち、spim起動時にロードする例外ハンドラコードexception.asには例外が渡されない、という実装になっているのです。 この例外ハンドラはMIPSのコードで書かれており、 spimがエミュレートするものです。 これでは自作のシステムコールを例外ハンドラコード内に記述できません。
これを解決するために、 spimのコマンドラインオプションに-aux_syscallを追加し、 このオプションをつけて起動された時は例外ハンドラに制御が移るようにしました。 これで自作のシステムコールを例外ハンドラコードに記述することができるようになります。
SPIM第7.3版に対する差分は以下の通りです。
diff -crN spim-7.3/CPU/spim.h spim-7.3-auxsyscall/CPU/spim.h *** spim-7.3/CPU/spim.h Tue Aug 29 11:23:17 2006 --- spim-7.3-auxsyscall/CPU/spim.h Fri Apr 18 09:37:07 2008 *************** *** 233,238 **** --- 233,239 ---- extern int force_break; /* Non-zero => stop interpreter loop */ extern int parser_error_occurred; /* Non-zero => parse resulted in error */ extern int spim_return_value; /* Value returned when spim exits */ + extern int aux_syscall; /* Non-zero => syscall exception in handler */ /* Actual type of structure pointed to depends on X/terminal interface */ extern port message_out, console_out, console_in; extern int mapped_io; /* Non-zero => activate memory-mapped IO */ diff -crN spim-7.3/CPU/syscall.c spim-7.3-auxsyscall/CPU/syscall.c *** spim-7.3/CPU/syscall.c Tue Aug 29 11:23:17 2006 --- spim-7.3-auxsyscall/CPU/syscall.c Fri Apr 18 09:51:38 2008 *************** *** 189,195 **** } default: ! run_error ("Unknown system call: %d\n", R[REG_V0]); break; } --- 189,199 ---- } default: ! if (aux_syscall == 0) { ! run_error ("Unknown system call: %d\n", R[REG_V0]); ! } else { ! raise_exception (ExcCode_Sys); ! } break; } diff -crN spim-7.3/spim/spim.c spim-7.3-auxsyscall/spim/spim.c *** spim-7.3/spim/spim.c Tue Aug 29 11:23:19 2006 --- spim-7.3-auxsyscall/spim/spim.c Fri Apr 18 10:01:51 2008 *************** *** 106,111 **** --- 106,112 ---- int mapped_io; /* Non-zero => activate memory-mapped IO */ int pipe_out; int spim_return_value; /* Value returned when spim exits */ + int aux_syscall; /* Non-zero => syscall exception in handler */ /* Local variables: */ *************** *** 139,144 **** --- 140,146 ---- accept_pseudo_insts = 1; quiet = 0; spim_return_value = 0; + aux_syscall = 0; /* Input comes directly (not through stdio): */ console_in.i = 0; *************** *** 221,226 **** --- 223,234 ---- exception_file_name = argv[++i]; load_exception_handler = 1; } + else if (streq (argv [i], "-aux_syscall") + || streq (argv [i], "-asysc")) + { aux_syscall = 1; } + else if (streq (argv [i], "-noaux_syscall") + || streq (argv [i], "-nasysc")) + { aux_syscall = 0; } else if (streq (argv [i], "-stext") || streq (argv [i], "-st")) { initial_text_size = atoi (argv[++i]); } *************** *** 294,300 **** -noquiet Print warnings (default)\n\ -mapped_io Enable memory-mapped IO\n\ -nomapped_io Do not enable memory-mapped IO (default)\n\ ! -fileAssembly code file and arguments to program\n"); } if (!assembly_file_loaded) --- 302,309 ---- -noquiet Print warnings (default)\n\ -mapped_io Enable memory-mapped IO\n\ -nomapped_io Do not enable memory-mapped IO (default)\n\ ! -file Assembly code file and arguments to program\n\ ! -aux_syscall Enable aux syscalls for exception handler\n"); } if (!assembly_file_loaded)