小坂の考察

test1はint(2byte)の変数を2つ受け取ってintの値を返している。
test1を呼び出す時,第1引数をR0に,第2引数をE0に載せて,test1にサブルーチンコールジャンプする。
test1では返す値をR0に載せてリターンジャンプしている。

test2はint(2byte)の変数を3つ受け取ってintの値を返している。
test2を呼び出す時,第1引数をR0に,第2引数をE0に,第3引数をR1に載せて,test2に飛ぶ。
test2では返す値をR0に載せて返している。

test3はlong int(4byte)の変数を2つ受け取ってlong intの値を返している。
test3を呼び出す時,第1引数をER0に,第2引数をER1に載せて,test3に飛ぶ。
test3では返す値をER0に載せて返している。
関数内ではER6を計算のために使うので,ER6の値を保護するため,push・popを行なって退避・復帰を行なっている。

test4はlong int(4byte)の変数を3つ受け取ってlong intの値を返している。
test4を呼び出す時,第1引数をER0に,第2引数をER1に載せて,第3引数をスタックに載せてtest4に飛ぶ。
test4では返す値をER0に載せて返している。
test4関数内ではER6を計算のために使うので,ER6の値を保護するため,push・popを行なって退避・復帰を行なっている。
関数に入ってきたときには,メモリのSP(stackpointer)の指す場所には,関数から戻るべき4byteのアドレスが載っており,
SP+4の位置には呼び出し側が載せた第3引数が載っている。
関数に入ってきたら,push ER6をするので,このpush命令直後では,SPの位置にpushされたER6の値,
SP+4の位置には関数から戻るべき4byteのアドレス,SP+8の位置には呼び出し側が載せた第3引数が載っている。
また,test4から戻った直後にはまだSPの位置には呼び出す前にpushした第3引数が入っているため,
これをpopしないとサブルーチンコール動作前の位置に戻らない。しかしpopすることでレジスタの不必要な変更をしたくない。そこでSPの値を4増やすだけで済む,ADDS.L #4,SPの命令を行なっている。

全体をまとめると,次のような規則になっているようである。
関数は他のところからも呼び出される可能性があるため,引数と返す値の取り扱いは,ある規則で統一的に作成されている。
呼び出し側もこの統一規則にしたがって引数を渡し,関数の値を受け取るようにすれば良い。
(1)関数呼び出しの時の引数に関して
いずれにしても,ER0とER1のみが,引数として利用され,ER2以降は引数伝達には使われない。

(2)関数の返す値について
(3)レジスタ利用の制限について
ER0,ER1の2つとER2以降のレジスタでは異なる制限がある


(上記の規則の一部は,下記のテストを追加することで確認できた。)
テストのCプログラム
int ans1;
int ans2;

test1(int a,int b,int c,int d)
{
    return a+b+c+d;
}

test2(int a,int b,int c,int d,int e)
{
    return a+b+c+d+e;
}

main()
{
    ans1=test1(100,200,300,400);
    ans2=test2(100,200,300,400,500);
}

翻訳されたアセンブリ言語ソース

_test1:
  PUSH.W      R6
  MOV.W       R0,R6
  ADD.W       E0,R6
  ADD.W       R1,R6
  ADD.W       E1,R6
  MOV.W       R6,R0
  POP.W       R6
  RTS

_test2:
  PUSH.W      R6
  MOV.W       R0,R6
  ADD.W       E0,R6
  ADD.W       R1,R6
  ADD.W       E1,R6
  MOV.W       @(6:16,SP),R0
  ADD.W       R6,R0
  POP.W       R6
  RTS

_main:
  MOV.W       #400:16,E1
  MOV.W       #300:16,R1
  MOV.W       #200:16,E0
  MOV.W       #100:16,R0
  BSR         _test1:8
  MOV.W       R0,@_ans1:24

  MOV.W       #500:16,R0
  PUSH.W      R0
  MOV.W       #400:16,E1
  MOV.W       #300:16,R1
  MOV.W       #200:16,E0
  MOV.W       #100:16,R0
  BSR         _test2:8
  ADDS.L      #2,SP
  MOV.W       R0,@_ans2:24
  RTS
  .SECTION    B,DATA,ALIGN=2
_ans1:
  .RES.W      1
_ans2:
  .RES.W      1
  .END