M16C（アセンブラ）＆名古屋のIoTは名古屋のOSで

M16C/60、M16C/20 、M16C/Tinyシリーズ ソフトウェアマニュアル
https://www.renesas.com/ja-jp/doc/products/mpumcu/002/rjj09b0136_m16csm.pdf

[R8C][M16C] インライン関数とインラインアセンブラとテンプレートの関係
http://www.kijineko.co.jp/tech/micom-memo/nc30/20111121-2

マイクロコンピュータとアセンブリ言語
http://www3.nit.ac.jp/~tamura/ex1/microcomputer.pdf

組込みモータ制御における人材育成教育カリキュラム開発
小峰 憲行*1, 山田 圀裕*2，豊田 恭平*3, 中村 俊雄*3
東海大学紀要情報通信学部
vol.6,No1,2013,pp.39-42
https://www.u-tokai.ac.jp/academics/undergraduate/information_and_telecommu/kiyou/index/pdf/vol_6_001/PP39-42.pdf

液晶表示ユニット MB-LCD1 アセンブラ・ライブラリによる制御,サンハヤト株式会社
http://www.sunhayato.co.jp/dcms_media/other/MB_LCD_1_SG043108.pdf

toppers-jsp/doc/m16c.txt
https://github.com/ryoon/toppers-jsp/blob/master/doc/m16c.txt

toppers-jsp/config/m16c-renesas/cpu_support.a30
https://github.com/ryoon/toppers-jsp/blob/master/config/m16c-renesas/cpu_support.a30

```ASM:toppers-jsp/config/m16c-renesas/cpu_support.a30
;*
;*  TOPPERS/JSP Kernel
;*      Toyohashi Open Platform for Embedded Real-Time Systems/
;*      Just Standard Profile Kernel
;*
;*  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
;*                              Toyohashi Univ. of Technology, JAPAN
;*  Copyright (C) 2003-2007 by Naoki Saito
;*             Nagoya Municipal Industrial Research Institute, JAPAN
;*  Copyright (C) 2003-2004 by Ryosuke Takeuchi
;*              Platform Development Center RICOH COMPANY,LTD. JAPAN
;*
;*  上記著作権者は，以下の (1)～(4) の条件か，Free Software Foundation 
;*  によって公表されている GNU General Public License の Version 2 に記
;*  述されている条件を満たす場合に限り，本ソフトウェア（本ソフトウェア
;*  を改変したものを含む．以下同じ）を使用・複製・改変・再配布（以下，
;*  利用と呼ぶ）することを無償で許諾する．
;*  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
;*      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
;*      スコード中に含まれていること．
;*  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
;*      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
;*      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
;*      の無保証規定を掲載すること．
;*  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
;*      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
;*      と．
;*    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
;*        作権表示，この利用条件および下記の無保証規定を掲載すること．
;*    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
;*        報告すること．
;*  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
;*      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
;*
;*  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
;*  よびTOPPERSプロジェクトは，本ソフトウェアに関して，その適用可能性も
;*  含めて，いかなる保証も行わない．また，本ソフトウェアの利用により直
;*  接的または間接的に生じたいかなる損害に関しても，その責任を負わない．
;* 
;*  @(#) $Id: cpu_support.a30,v 1.7 2007/03/23 07:06:35 honda Exp $


;
;	プロセッサ依存モジュール アセンブリ言語部（M16C用）
;

;
;  offset.incはmakeoffset.cとm16coffset.exeコマンドにより
;  自動生成される．
;
	.include	offset.inc

	.glb	__kernel_runtsk
	.glb	__kernel_schedtsk
	.glb	__kernel_reqflg
	.glb	__kernel_enadsp

	.glb	__kernel_dispatch
	.glb	__kernel_exit_and_dispatch
	.glb	__kernel_activate_r
	.glb	__kernel_call_texrtn
	.glb	__kernel_interrupt
	.glb	__kernel_intnest

	.glb	_iana_tsk
	.glb	__kernel_break_wait

	.section	program, code, align
;
;	タスクディスパッチャ
;
;   dispatch は，タスクコンテキスト状態・割込み禁止状態で呼び出さなけ
;   ればならない．exit_and_dispatch も，タスクコンテキスト状態・割込
;   み禁止状態で呼び出すのが原則であるが，カーネル起動時に対応するため，
;   割込みモードで呼び出した場合にも対応している．
;	呼び出し条件: IPL=0, FLGレジスタIビット=0 (CPUロック状態),
;			intnest = 0(タスクコンテキスト), タスクスタック
;
__kernel_dispatch:
	pushm	sb, fb				; スタックへレジスタ保存
	mov.w	__kernel_runtsk, a0
	stc	isp, TCB_sp[a0]			; スタックポインタをTCBに保存
	mov.w	#(dispatch_r>>16), TCB_pc+2[a0]	; 実行再開番地をTCBに保存
	mov.w	#(dispatch_r & 0ffffh), TCB_pc[a0]
	jmp.b	dispatcher
;
;	呼び出し条件: IPL=0, FLGレジスタIビット=0 (CPUロック状態),
;			intnest = 0(タスクコンテキスト), タスクスタック
;
;	a0 にはruntsk のアドレスが格納されている
;
dispatch_r:
	popm	sb,fb						; タスクスタックからレジスタ復帰
	mov.w	TCB_enatex[a0], r0
	btst	TCB_enatex_bit, r0			; タスク例外処理許可?
	jz	dispatch_r_1					; 許可でなければ dispatch_r_1 へ
	mov.w	TCB_texptn[a0], r0				; 保留例外要因があるか？
	jz	dispatch_r_1					; なければ dispatch_r_1 へ
	jmp	__kernel_call_texrtn	; タスク例外ハンドラへ
dispatch_r_1:				; タスク例外を実行しない場合
	rts				; dispatch 呼び出し元へ戻る.


;
;	タスク起動時処理
;
;	ここでは, CPUロック解除状態にし, タスクを起動する.
;
;	呼出条件: FLGレジスタIビット=0 (CPUロック状態), タスクスタック
;		IPL=0, タスクコンテキスト(intnest=0)
;
__kernel_activate_r:
	pop.w	a0		; タスクの起動番地をA1A0に設定
	pop.w	a1
	ldc	#0040h, flg	; 割込み許可, ISP, IPL=0
	jmpi.a	a1a0

;
;	dispatch呼び出し条件:
;		・すべてのタスクのコンテキストは保存されている.
;		・FLGレジスタIビット=0 (CPUロック状態)
;		・コンテキストはタスクコンテキスト(intnest=0)
;		　但し、exit_and_dispatchについてはモニター起動等を考慮
;		　した上記以外の呼び出し条件の対応を行う
;	dispatcher 呼出時のスタック:
;		__kernel_dispatch からきた場合: タスクスタック
;		exit_and_dispatch からきた場合: 
;			exit_task からきた場合はタスクスタック
;			カーネル起動時は割込みスタック
;		ret_int からきた場合: 割込みスタック
;		dispatcher_2 での割込み待ちからきた場合: 割込みスタック
;

__kernel_exit_and_dispatch:
	fclr	i			; 割込み禁止
	mov.b	#0, __kernel_intnest	; ネストカウンタクリア
dispatcher:
	mov.w	__kernel_schedtsk, a0	; 
	mov.w 	a0, __kernel_runtsk	; schedtsk を runtsk に
	.IF MON == 1
;   タスクモニター機能用分岐
;   不要の場合は (MON = 0)
	jsr.a  _iana_tsk			; タスク実行情報の設定
	mov.w	__kernel_runtsk,a0	; a0を復帰
	.ENDIF
	jz	dispatcher_1		; schedtsk がなければ割込み待ち
	ldc	TCB_sp[a0], isp		; タスクスタックポインタを復帰
	jmpi.a	TCB_pc[a0] 		; 実行再開番地へジャンプ
;
;	schdedtskが NULL の場合は、これより下には行かない
;
dispatcher_1:
	ldc	#RAMEND, isp		; 割込み用のスタックへ切替え
	inc.b	__kernel_intnest	; 非タスクコンテキスト
dispatcher_2:
	fset	i		; 割込み待ち
	wait 			; wait命令を使用すると
	nop			; 消費電力を抑えることができる.
	nop			; コメントをつけたまま(nopのみ)にすると
	nop			; アイドルループと同じような動作になる.
	nop			; 
;
;	ここで非タスクコンテキスト,割込みスタックに切り換えたのは,
;	ここで発生する割込み処理にどのスタックを使うかという問題の解決と,
;	割込みハンドラ内でのディスパッチ防止という2つの意味がある．
;
	fclr	i			; 割込み禁止
	mov.w	__kernel_reqflg, r0	; reqflg が FALSE なら
	jz	dispatcher_2		; dispatcher_2 へ
	mov.w	#0, __kernel_reqflg	; reqflgがTRUEならFALSEにする
	dec.b	__kernel_intnest	; タスクコンテキストに戻す
	jmp.b	dispatcher		; dispatcher へ戻る


;
;  割込みハンドラ/CPU例外ハンドラ出口処理
;
;	呼出し条件:
;	・FLGレジスタのIビット=0, IPL=0, タスクコンテキスト(intnest=0)
;	・使用スタックはタスクスタック, reqflg = TRUE
;
ret_int:
	mov.w	#0, __kernel_reqflg		; reqflg <--- FALSE
	mov.w	__kernel_runtsk, a0		; A0 <--- runtsk
	mov.w	__kernel_enadsp, r0		; enadsp が FALSE なら
	jz	ret_int_r			; ret_int_r へ
	mov.w	__kernel_schedtsk, r0		; schedtskと
	cmp.w	a0, r0				; runtsk が同じなら
	jeq	ret_int_r			; ret_int_r へ
		;;;; (runtsk == NULL) のチェックは必要ないため削除 (07/03/02)
	stc	isp, TCB_sp[a0]			; タスクスタックを保存
	mov.w	#(ret_int_r&0ffffh), TCB_pc[a0]	; 実行再開番地を保存
	mov.w	#(ret_int_r>>16), TCB_pc+2[a0]
	jmp.b	dispatcher

__kernel_break_wait:
ret_int_r:
	mov.w	TCB_enatex[a0],r0	; enatex が FALSE ならリターン
	btst	TCB_enatex_bit,r0
	jz	ret_int_r_1
	mov.w	TCB_texptn[a0],r0	; texptn が 0 ならばリターン
	jz	ret_int_r_1
	jsr.a	__kernel_call_texrtn	; タスク例外処理ルーチンの呼出し
ret_int_r_1:
	popm	r0,r1,r2,r3,a0,a1,sb,fb	; スタックからレジスタを復帰
	reit				; タスクへ戻る


;
;	割込み/CPU例外の出入口処理(アセンブリ言語記述部分)
;
;	呼出し条件:
;	・FLGレジスタのIビット=0, IPLは受付けた割込みのIPL.
;	・スタックは多重割り込みなら割込みスタック, そうでなければ
;	  タスクスタック
;	・a1とa0 には割込み/CPU例外ハンドラのアドレスが格納されている.
;	・r1 には(タスクor割込み)スタックポインタの値が格納されている.
;	これはそのままCPU例外ハンドラに渡すVP型の変数 p_excinf となる.
;
;	レジスタがスタック上にどのように保存されているかを以下に示す.
;	この図では上が低位, 下が高位のアドレスで, スタックは下から
;	上方向に向かって積み上げられるものとする.
;
;	--------------------------------------
;	|              R0(2byte)             | <--- p_excinf
;	|                                    |
;	--------------------------------------
;	|              R1(2byte)             |
;	|                                    |
;	--------------------------------------
;	|              R2(2byte)             |
;	|                                    |
;	--------------------------------------
;	|              R3(2byte)             |
;	|                                    |
;	--------------------------------------
;	|              A0(2byte)             |
;	|                                    |
;	--------------------------------------
;	|              A1(2byte)             |
;	|                                    |
;	--------------------------------------
;	|              SB(2byte)             |
;	|                                    |
;	--------------------------------------
;	|              FB(2byte)             |
;	|                                    |
;	--------------------------------------
;	|           PCの下位2バイト          |
;	|                                    |
;	--------------------------------------
;	|          FLGの下位1バイト          |
;	--------------------------------------
;	|  FLGの上位4ビット/PCの上位4ビット  |
;	--------------------------------------
;
;	ハンドラからリターンした後は, 多重割込みでなく, かつ reqflg が
;	TRUE になった時に，ret_int へ分岐する．
;
;	多重割込みかどうかは割込みネストカウンタの値で判定する.
;	intnest != 0 ならば多重割込みであると判定する.
;
;	reqflg はCPUロック状態でチェックする. そうでないと，
;	reqflg チェック後に起動された割込みハンドラ内で
;	ディスパッチが要求された場合に，ディスパッチされない.
;
__kernel_interrupt:
	cmp.b	#0, __kernel_intnest	; 多重割り込みかどうか
	jnz	int_from_int		; 0でなければ多重割込み
int_from_task:				; 初段の割込み
	ldc	#RAMEND, isp		; 割込み用のスタックへ切替える
	push.w	r1		; スタックポインタを割込みスタックへ保存
int_from_int:				; 多重割込み
	inc.b	__kernel_intnest	; ネスト回数をインクリメント
	fset	i			; 割込み禁止解除
	jsri.a	a1a0			; Cルーチン呼び出し
	fclr	i			; 割込み禁止
	dec.b	__kernel_intnest	; ネスト回数をデクリメント
	jnz	int_return		; 多重割り込みならリターン
int_from_task2:				; 初段の割込み
	pop.w	r1			; タスクスタックポインタを戻す
	ldc	r1, isp
	ldipl	#0			; タスクのIPL値をセット(IPL=0)
	mov.w	__kernel_reqflg, r1	; ディスパッチ要求がないか?
	jz	int_return		; なければ割込み発生元のタスクに戻る
	jmp.b	ret_int			; あれば ret_int へジャンプ
int_return:
	popm	r0,r1,r2,r3,a0,a1,sb,fb	; レジスタ復帰
	reit				; 割込み前の処理に戻る

;
;  微少時間待ち
;
SIL_DLY_TIM1	.equ	625	; 最小時間(ループ0回)[ns]
SIL_DLY_TIM2	.equ	250	; ループ1回あたりの時間[ns]

	.glb	$sil_dly_nse
$sil_dly_nse:
	sub.w #SIL_DLY_TIM1, r1
	jgtu L0
	rts
L0:
	sub.w #SIL_DLY_TIM2, r1
	jgtu L0
	rts


	; 未使用割込みの処理
	.glb _unused_interrupt
_unused_interrupt:
	reit

	.end
```
### 最後までおよみいただきありがとうございました。
いいね　💚、フォローをお願いします。
####  Thank you very much for reading to the last sentence.
Please press the like icon 💚　and follow me for your happy life.