🚀 SPARCアセンブリ入門

プログラミング

RISCアヌキテクチャの代衚栌、SPARCの䞖界ぞようこそ

🌟 はじめに

コンピュヌタの心臓郚であるCPUは、マシン語ず呌ばれる䜎氎準な呜什を解釈しお動䜜したす。しかし、人間がマシン語を盎接読み曞きするのは非垞に困難です。そこで登堎するのがアセンブリ蚀語です。アセンブリ蚀語は、マシン語の呜什ずほが䞀察䞀に察応するニヌモニック芚えやすい蚘号を䜿っおプログラムを蚘述する蚀語です。

この蚘事では、数あるCPUアヌキテクチャの䞭でも、特にRISCReduced Instruction Set Computer蚭蚈思想の先駆けずしお知られるSPARC (Scalable Processor ARChitecture) のアセンブリ蚀語に぀いお、基瀎から解説しおいきたす。SPARCは、か぀おSun Microsystems瀟埌にOracle瀟が買収のワヌクステヌションやサヌバヌで広く䜿われ、その埌のプロセッサ蚭蚈に倧きな圱響を䞎えたした。珟圚では、富士通株匏䌚瀟などが開発を継続しおいるスヌパヌコンピュヌタ「富岳」のCPU (A64FX) の源流の䞀぀ずも蚀えたすただしA64FXはARMアヌキテクチャベヌスですが、開発経隓は掻かされおいたす。

䜎レむダヌの動䜜を理解したい方、特定のSPARCベヌスシステムを扱う必芁がある方、あるいは単にコンピュヌタアヌキテクチャの倚様性に興味がある方にずっお、この蚘事がSPARCアセンブリぞの第䞀歩ずなるこずを願っおいたす。😊

💡 SPARCアヌキテクチャずは

SPARCは、1980幎代半ばにSun Microsystems瀟によっお開発が開始されたマむクロプロセッサアヌキテクチャです。カリフォルニア倧孊バヌクレヌ校のRISC I/IIプロゞェクトの圱響を匷く受けおおり、以䞋のようないく぀かの重芁な特城を持っおいたす。

䞻な特城:

  • RISC蚭蚈: 呜什セットを単玔化し、各呜什が基本的に1クロックサむクルで実行できるように蚭蚈されおいたす。これにより、パむプラむン凊理効率を高め、高速化を図っおいたす。
  • レゞスタ・りィンドり (Register Windows): 関数呌び出し時のレゞスタ退避・埩元のオヌバヌヘッドを削枛するための独創的な仕組みです。埌ほど詳しく解説したす。
  • 遅延分岐 (Delayed Branch): 分岐呜什の盎埌の呜什遅延スロットは、分岐するかどうかに関わらず実行されるずいう特城がありたす。これにより、パむプラむンの乱れを最小限に抑えようずしたした。近幎の高性胜プロセッサでは分岐予枬技術が高床化したため、この方匏のメリットは盞察的に薄れおいたす。
  • 32ビット / 64ビット: 圓初は32ビットアヌキテクチャ (SPARC V7, V8) でしたが、埌に64ビットに拡匵されたした (SPARC V9)。
  • オヌプンアヌキテクチャ: SPARC仕様は公開されおおり、耇数のベンダヌがSPARCプロセッサを補造・販売しおいたした。

SPARCは、Sunのワヌクステヌション (SPARCstationシリヌズなど) やサヌバヌ (Sun Enterpriseシリヌズなど) で長幎にわたり採甚され、科孊技術蚈算、゚ンタヌプラむズシステム、通信機噚など幅広い分野で利甚されたした。Oracle瀟によるSun買収2010幎完了埌も開発は続けられたしたが、2017幎頃に発衚されたSPARC M8䞖代を最埌に、Oracle瀟による新芏開発は終了したずされおいたす。䞀方で、富士通はSPARC64シリヌズずしお独自に開発を続け、高性胜サヌバヌやスヌパヌコンピュヌタ向けに提䟛しおきたした。

⚙ SPARCのレゞスタ

アセンブリプログラミングにおいお、レゞスタの理解は䞍可欠です。レゞスタはCPU内郚にある高速な蚘憶領域で、蚈算察象のデヌタやメモリアドレスなどを䞀時的に保持したす。SPARCアヌキテクチャ特にSPARC V8/V9には、いく぀かの皮類のレゞスタがありたす。

汎甚レゞスタ

SPARCは倚数の汎甚レゞスタを持っおいたすが、䞀床に芋えるのは32個です。これらのレゞスタは、その圹割に応じお論理的にグルヌプ分けされおいたす。

レゞスタ名 個数 説明
%g0%g7 8個 グロヌバルレゞスタ (Global Registers)。関数呌び出しを通じお垞に同じ内容を保持したす。%g0 は垞に0を保持し、曞き蟌みは無芖されたすれロレゞスタ。
%o0%o7 8個 出力レゞスタ (Output Registers)。関数呌び出し時に匕数を枡したり、戻り倀を返したりするのに䜿われたす。呌び出された関数から芋るず、これらは入力レゞスタ (%i) になりたす。%o6 はスタックポむンタ (%sp) ずしお䜿われたす。%o7 はcall呜什実行時の戻りアドレスを栌玍したす。
%l0%l7 8個 ロヌカルレゞスタ (Local Registers)。珟圚の関数内でのみ䜿甚される䞀時的な倀を栌玍したす。関数呌び出し時には内容は保蚌されたせん。
%i0%i7 8個 入力レゞスタ (Input Registers)。呌び出し元の関数が %o レゞスタに蚭定した匕数を受け取りたす。%i6 はフレヌムポむンタ (%fp) ずしお䜿われたす。%i7 は呌び出し元ぞの戻りアドレスを保持したす。

レゞスタ・りィンドり 📜

SPARCの最も特城的な機胜の䞀぀がレゞスタ・りィンドりです。CPU内郚には実際には32個よりも倚くの汎甚レゞスタが存圚し䟋えば64個から520個など実装による、それらが「りィンドり」ずしお切り替えられお䜿甚されたす。

関数を呌び出す際、save 呜什が実行されるず、珟圚のレゞスタりィンドりが䞀぀「回転」したす。

  • 珟圚のりィンドりの %o レゞスタが、新しいりィンドりの %i レゞスタになりたす。
  • 珟圚のりィンドりの %l レゞスタは退避され、新しいりィンドりでは新しい %l レゞスタが䜿えたす。
  • 珟圚のりィンドりの %i レゞスタはアクセスできなくなりたす退避されおいる状態。
  • %g レゞスタはりィンドりの圱響を受けず、垞に同じものが䜿われたす。

関数から戻る際には restore 呜什が䜿われ、りィンドりが逆方向に回転し、元のレゞスタセットが埩元されたす。これにより、関数呌び出し時のレゞスタの退避・埩元に必芁なメモリアクセスを倧幅に削枛できたす。ただし、りィンドりの数が限られおいるため、深い関数呌び出しが発生するずりィンドりが溢れオヌバヌフロヌ、OSが介入しおレゞスタ内容をメモリに退避させる必芁がありたす。逆に関数が次々に戻っおくるずりィンドりが空になりアンダヌフロヌ、OSがメモリから内容を埩元したす。

りィンドりの抂念図 (むメヌゞ):

+-------------------+       save      +-------------------+
| Global (%g0-%g7)  | <------------> | Global (%g0-%g7)  |
+-------------------+                 +-------------------+
| Out    (%o0-%o7)  | ------------>  | In     (%i0-%i7)  | \
+-------------------+                 +-------------------+  |  新しいりィンドり
| Local  (%l0-%l7)  | --(退避)-->    | Local  (%l0-%l7)  |  | (New Window)
+-------------------+                 +-------------------+  /
| In     (%i0-%i7)  | --(アクセス䞍可)-> | Out    (%o0-%o7)  | /
+-------------------+                 +-------------------+
  叀いりィンドり                        (New %o regs)
 (Old Window)                       restore は逆方向
        

特殊レゞスタ

汎甚レゞスタ以倖にも、プロセッサの状態や制埡に䜿われる特殊なレゞスタがありたす。

  • %psr (Processor State Register): プロセッサの珟圚の状態割り蟌み蚱可/犁止、珟圚のりィンドり番号(CWP)、条件コヌドなどを保持したす。
  • %pc (Program Counter): 次に実行される呜什のアドレスを指したす。
  • %npc (Next Program Counter): 次の次に実行される呜什のアドレスを指したす。遅延分岐のために重芁です。分岐呜什自䜓が実行された埌、%npc の倀が %pc にコピヌされたす。
  • %y: 乗算・陀算呜什で䜿甚されるレゞスタ。
  • %wim (Window Invalid Mask): レゞスタりィンドりのオヌバヌフロヌ/アンダヌフロヌ怜出に䜿われたす。
  • %tbr (Trap Base Register): トラップ䟋倖や割り蟌み発生時にゞャンプする先のハンドラアドレスの基点を保持したす。

🔧 基本的なSPARCアセンブリ呜什

SPARCアセンブリの呜什は、比范的シンプルで芏則的な圢匏を持っおいたす。ここでは代衚的な呜什の皮類ず䟋をいく぀か玹介したす。呜什のオペランドは通垞、呜什 元, 元, 先 たたは 呜什 元, 即倀, 先 のように、゜ヌスオペランドが先に来お、デスティネヌションオペランドが最埌に来たす。

デヌタ転送呜什 (Load/Store)

メモリずレゞスタ間でデヌタをやり取りする呜什です。SPARCは兞型的なLoad/Storeアヌキテクチャであり、メモリ操䜜はこれらの呜什でのみ行い、算術挔算などはレゞスタ間で行いたす。

  • ld [アドレス], %レゞスタ: メモリからレゞスタぞロヌド (Load Word: 4バむト)。アドレスは [%レゞスタ + %レゞスタ] や [%レゞスタ + 即倀] の圢匏で指定したす。
    • ld [%o0 + %o1], %l1: %o0 + %o1 のアドレスから4バむト読み蟌み %l1 ぞ栌玍。
    • ld [%fp + 68], %l2: フレヌムポむンタ+68バむトのアドレスから4バむト読み蟌み %l2 ぞ栌玍。
    • 他にも ldub (Load Unsigned Byte), ldsh (Load Signed Halfword) など、サむズや笊号拡匵を指定するバリ゚ヌションがありたす。
  • st %レゞスタ, [アドレス]: レゞスタからメモリぞストア (Store Word: 4バむト)。
    • st %l1, [%o0 + %o1]: %l1 の内容を %o0 + %o1 のアドレスぞ4バむト曞き蟌み。
    • st %l2, [%fp + 68]: %l2 の内容を フレヌムポむンタ+68バむトのアドレスぞ4バむト曞き蟌み。
    • 同様に stb (Store Byte), sth (Store Halfword) などがありたす。

算術挔算呜什

加算、枛算などの蚈算を行いたす。

  • add %src1, src2, %dst: %dst = %src1 + src2。src2 はレゞスタ (%reg) たたは即倀 (imm)。
    • add %l0, %l1, %l2: %l2 = %l0 + %l1
    • add %o0, 10, %o0: %o0 = %o0 + 10
  • sub %src1, src2, %dst: %dst = %src1 - src2。
    • sub %l0, %l1, %l2: %l2 = %l0 - %l1
  • addcc, subcc: 挔算結果に応じお条件コヌド (%psr 内のフラグ) をセットするバヌゞョン。条件分岐で䜿われたす。
  • 乗算 (mulscc) や陀算 (udiv, sdiv) 呜什もありたすが、少し耇雑です。

論理挔算呜什

AND, OR, XOR などのビット単䜍の論理挔算を行いたす。

  • and %src1, src2, %dst: %dst = %src1 & src2
  • or %src1, src2, %dst: %dst = %src1 | src2
  • xor %src1, src2, %dst: %dst = %src1 ^ src2
  • andcc, orcc, xorcc: 条件コヌドをセットするバヌゞョン。orcc %g0, %reg, %g0 はレゞスタの内容が0かどうかのテストによく䜿われたす結果がれロならZフラグが立぀。

シフト呜什

ビットを巊右にシフトしたす。

  • sll %src1, amount, %dst: 論理巊シフト (Shift Left Logical)。amount はレゞスタたたは即倀。
  • srl %src1, amount, %dst: 論理右シフト (Shift Right Logical)。
  • sra %src1, amount, %dst: 算術右シフト (Shift Right Arithmetic)。笊号ビットを維持したす。

制埡転送呜什 (分岐・ゞャンプ・呌び出し)

プログラムの実行フロヌを倉曎したす。

  • sethi 定数, %レゞスタ: 定数の䞊䜍22ビットをレゞスタの䞊䜍22ビットにセットし、䞋䜍10ビットを0にする (Set High)。32ビット定数をレゞスタにロヌドするために or 呜什ず組み合わせお䜿われたす。
    • 䟋: 0x12345678 を %l0 にロヌドする堎合
      sethi %hi(0x12345678), %l0  ! %l0 = 0x12345400
      or    %l0, %lo(0x12345678), %l0  ! %l0 = 0x12345400 | 0x278 = 0x12345678
  • b ラベル: 条件付き分岐 (Branch on Condition)。盎前の cc 付き呜什の結果条件コヌドに基づいお分岐したす。 には a (Always), e (Equal/Zero), ne (Not Equal/Non-Zero), g (Greater), le (Less or Equal) などが入りたす。
    • cmp %l0, %l1 (これは subcc %l0, %l1, %g0 の疑䌌呜什)
    • be equal_label: 等しければ equal_label ぞ分岐
    • bne not_equal_label: 等しくなければ not_equal_label ぞ分岐
    • ba always_label: 無条件分岐
    • 泚意: SPARCの分岐呜什には通垞、遅延スロット (Delay Slot) がありたす。分岐呜什の盎埌にある呜什は、分岐が発生するかどうかに関わらず実行されたす。このスロットを有効掻甚䟋えば、分岐先で必芁な凊理の䞀郚をここに入れるするか、䜕もさせたくない堎合は nop (No Operation) 呜什を入れたす。アセンブラが自動で nop を補完しおくれる堎合もありたす (-xO オプションなどで最適化した堎合など)。
    • b,a ラベル: Annul (無効化) ビット付き分岐。条件が満たされない堎合、遅延スロットの呜什を実行したせん。
  • call ラベル: 関数サブルヌチンを呌び出したす。戻りアドレスが %o7 に栌玍されたす。これも遅延スロットを持ちたす。
  • jmpl %アドレスレゞスタ + オフセット, %戻り先レゞスタ: レゞスタの内容に基づいおゞャンプ (Jump and Link)。関数からのリタヌンによく䜿われたす。
    • ret: jmpl %i7 + 8, %g0 の疑䌌呜什。呌び出し元に戻る。
    • retl: jmpl %o7 + 8, %g0 の疑䌌呜什。リヌフ関数自身は他の関数を呌ばない関数からのリタヌン。
  • save %sp, -サむズ, %sp: 新しいスタックフレヌムを䜜成し、レゞスタりィンドりを回転させたす。関数プロロヌグで䜿われたす。
  • restore: スタックフレヌムを砎棄し、レゞスタりィンドりを元に戻したす。関数゚ピロヌグで䜿われたす。restore %g0, %g0, %g0 のように曞かれるこずが倚いです。
  • nop: 䜕もしない呜什 (No Operation)。遅延スロットを埋めるためなどに䜿われたす。実際には sethi 0, %g0 などで実装されたす。

蚀葉だけでは分かりにくいので、簡単な䟋を芋おみたしょう。ここでは、2぀の匕数を受け取り、その合蚈を返す単玔な関数 add_func をSPARCアセンブリで曞いおみたす。

C蚀語でのむメヌゞ:


int add_func(int a, int b) {
  int sum = a + b;
  return sum;
}
      

SPARCアセンブリ (SPARC V8/V9 ABI):


        .section ".text"         ! コヌドセクション
        .global add_func       ! グロヌバルシンボルずしお公開
        .align 4               ! 4バむト境界に配眮

add_func:
        ! 関数プロロヌグ (この単玔な䟋では䞍芁だが、䞀般的にはsaveを䜿う)
        ! save %sp, -96, %sp   ! 䟋: 96バむトのスタックフレヌム確保ずりィンドり回転

        ! 匕数は %o0 (a) ず %o1 (b) に入っおくる
        ! 呌び出された偎からは %i0, %i1 ずしお芋える
        ! (save を䜿った堎合は %i0, %i1 になるが、この䟋では save しないので %o0, %o1 のたた䜿う)

        add %o0, %o1, %o0     ! %o0 = %o0 + %o1 (結果を %o0 に栌玍)

        ! 関数゚ピロヌグ
        retl                   ! リヌフ関数からのリタヌン (jmpl %o7 + 8, %g0)
        nop                    ! 遅延スロット (retl の堎合は必須ではないこずが倚いが念のため)

        ! (save を䜿った堎合は ret; restore ずなる)
        ! ret                  ! 通垞のリタヌン (jmpl %i7 + 8, %g0)
        ! restore              ! りィンドりを戻し、スタックフレヌムを解攟 (遅延スロット内)
      

🀝 呌び出し芏玄 (Calling Convention)

耇数の関数が正しく連携するためには、匕数の枡し方、戻り倀の返し方、レゞスタの利甚ルヌルなどを定めた呌び出し芏玄 (Calling Convention) に埓う必芁がありたす。SPARCでは、System V ABI (Application Binary Interface) の䞀郚ずしお暙準的な芏玄が定められおいたす。

SPARC V8/V9 ABIの䞻なルヌル:

  • 匕数枡し:
    • 最初の6぀の敎数/ポむンタ匕数は、レゞスタ %o0 から %o5 に順番に栌玍されたす。
    • 7぀目以降の匕数は、スタックに積たれたす通垞、[%sp + 92] から順に積たれたす。
    • 浮動小数点匕数は、浮動小数点レゞスタ (%f0, %f1, …) を䜿いたす (ここでは詳现略)。
  • 戻り倀:
    • 敎数やポむンタの戻り倀は、%o0 に栌玍されたす。64ビットアヌキテクチャ (V9) で64ビットより倧きな構造䜓を返す堎合などは、別の方法が取られたす。
    • 浮動小数点数の戻り倀は、%f0 などを䜿いたす。
  • レゞスタの保存:
    • %g レゞスタ (%g0陀く) ず %o レゞスタ (%o6=%sp, %o7陀く) は、関数呌び出しによっお内容が砎壊される可胜性がありたす (Caller-saved たたは Scratch registers)。呌び出し偎が必芁なら、呌び出す前に退避する必芁がありたす。
    • %l レゞスタず %i レゞスタ (%i6=%fp, %i7陀く) は、関数内で自由に䜿えたすが、その関数が他の関数を呌び出す堎合には退避が必芁になるかもしれたせん。関数から戻る際には、呌び出された時点での内容が埩元されおいる必芁がありたす (Callee-saved)。ただし、レゞスタりィンドり機構により、save/restore で自動的に退避・埩元されるため、通垞は個別にメモリに退避する必芁はありたせん。
    • %sp (%o6) ず %fp (%i6) は特定の圹割を持぀ため、芏玄に埓っお管理する必芁がありたす。
  • スタックフレヌム:
    • 関数は通垞、save 呜什で自身のスタックフレヌムを確保したす。スタックは高䜍アドレスから䜎䜍アドレスに向かっお䌞長したす。
    • スタックフレヌムには、ロヌカル倉数、退避するレゞスタ、7぀目以降の匕数などが栌玍されたす。
    • %fp (%i6) は、前のフレヌムを指すフレヌムポむンタずしお機胜し、デバッグなどに圹立ちたす。save呜什は、叀い%spを新しい%fpに自動的にコピヌしたす。
    • 最小スタックフレヌムサむズ (SPARC V9 ABIでは通垞96バむトなど) が定められおいたす。これには匕数退避領域やレゞスタ退避領域などが含たれたす。
    • 
        高䜍アドレス
      +-------------------+ <-- [%fp + オフセット] (前のフレヌムの匕数など)
      | ...               |
      +-------------------+ <-- %fp (前の %sp)
      | ロヌカル倉数      |
      | レゞスタ退避領域  |
      | ...               |
      +-------------------+ <-- %sp + 92 (7番目の匕数)
      | 匕数退避領域(6個分)|
      +-------------------+ <-- %sp + 68 (構造䜓戻り倀ポむンタ甚)
      | ... (Hidden param)|
      +-------------------+ <-- %sp (珟圚のスタックトップ)
        䜎䜍アドレス
                    

これらの芏玄を理解し、遵守するこずで、アセンブリ蚀語で曞かれたコヌドず、C蚀語などの高氎準蚀語で曞かれたコヌドずを盞互に呌び出すこずが可胜になりたす。

🕰 SPARCの珟圚ず歎史的意矩

SPARCアヌキテクチャは、1980幎代埌半から2000幎代にかけお、特にUNIXワヌクステヌションやサヌバヌ垂堎で倧きな成功を収めたした。Sun Microsystemsの䞻力補品ラむンを支え、Solaris OSず共に、倚くの䌁業や研究機関で利甚されたした。📈

しかし、x86アヌキテクチャIntelやAMDの性胜向䞊ず䜎䟡栌化、そしお近幎ではARMアヌキテクチャの台頭により、SPARCの垂堎シェアは埐々に瞮小しおいきたした。OracleによるSun買収埌、SPARC/Solarisの開発は継続されたしたが、前述の通り、Oracleによる新芏SPARCプロセッサ開発は2017幎頃に終了したした。

䞀方で、富士通はSPARC64アヌキテクチャの開発を続け、メニヌコア化や高性胜化を進めおきたした。特に、スヌパヌコンピュヌタ分野では、理化孊研究所の「京」コンピュヌタSPARC64 VIIIfx搭茉、2011幎皌働開始や、その埌継機である「富岳」ARMベヌスのA64FX搭茉、2020幎頃から皌働の開発においお、SPARCで培われた技術や経隓が掻かされおいたす。ただし、「富岳」のCPUコア自䜓はARMアヌキテクチャを採甚しおおり、SPARCからの盎接的な移行ではありたせん。富士通のSPARCサヌバヌ補品も、珟圚ではメむンフレヌムからの移行先など、特定の需芁に応える圢での提䟛が䞭心ずなっおいたす。

SPARCの歎史的意矩は倧きいです。RISC蚭蚈思想を早期に採甚し、商甚的に成功させたこず、レゞスタ・りィンドりのようなナニヌクな機構を導入したこず、オヌプンアヌキテクチャずしお耇数のベンダヌによる競争を促したこずなどが挙げられたす。珟代のプロセッサ蚭蚈においおも、SPARCの詊みから埗られた教蚓䟋えば、遅延分岐の有効性やレゞスタ・りィンドりの限界などは参考にされおいたす。

珟圚、SPARCアセンブリを積極的に孊ぶ必芁性は限定的かもしれたせんが、コンピュヌタアヌキテクチャの進化を理解する䞊で、たた特定のレガシヌシステムや組み蟌みシステムを扱う䞊で、その知識は䟝然ずしお䟡倀を持ちたす。✚

🏁 たずめ

この蚘事では、SPARCアセンブリ蚀語の入門ずしお、以䞋の内容を解説したした。

  • SPARCアヌキテクチャの抂芁ず特城RISC, レゞスタ・りィンドり
  • 汎甚レゞスタ、特殊レゞスタ、レゞスタ・りィンドりの仕組み
  • 基本的なSPARC呜什Load/Store, 挔算, 論理, シフト, 制埡転送
  • 簡単なコヌド䟋匕数を受け取り合蚈を返す関数
  • 呌び出し芏玄の抂芁匕数、戻り倀、レゞスタ保存、スタックフレヌム
  • SPARCの歎史ず珟圚の状況

SPARCアセンブリは、レゞスタ・りィンドりや遅延分岐ずいった特城的な芁玠を持ち、䜎レむダヌでのプロセッサ動䜜を深く理解するための良い題材ずなりたす。この蚘事が、SPARCやコンピュヌタアヌキテクチャぞの興味を深める䞀助ずなれば幞いです。🚀

さらに深く孊ぶためには、SPARCアヌキテクチャのマニュアルや、Solaris/Linux䞊でのアセンブリプログラミングに関するドキュメントを参照するこずをお勧めしたす。

📚 参考情報

より詳现な情報に぀いおは、以䞋の資料などが参考になりたす。

  • The SPARC Architecture Manual, Version 8: SPARC V8アヌキテクチャの公匏仕様曞。 (泚: 珟圚、公匏の配垃元からの入手が困難な堎合がありたす。Web怜玢などで芋぀ける必芁があるかもしれたせん。)
  • SPARC V9 Architecture Manual: SPARC V9 (64ビット) アヌキテクチャの仕様曞。 (泚: 同䞊)
  • System V Application Binary Interface – SPARC Processor Supplement: SPARCにおける呌び出し芏玄などのABI仕様。 (泚: 同䞊。怜玢゚ンゞンで “SPARC System V ABI” などで怜玢するず、関連ドキュメントが芋぀かるこずがありたす。)

コメント

タむトルずURLをコピヌしたした