MicroBlaze(アセンブラ)＆名古屋のIoTは名古屋のOSで

MicroBlaze ソフト プロセッサ コア
https://japan.xilinx.com/products/design-tools/microblaze.html

MicroBlaze プロセッサ リファレンス ガイド
https://www.xilinx.com/support/documentation/sw_manuals_j/xilinx2015_4/ug984-vivado-microblaze-ref.pdf

カスタム設計の MicroBlaze
http://bitcraft.web.fc2.com/embedded/microblaze/microblaze.html

toppers-jsp/config/microblaze/cpu_support.S
https://github.com/ryoon/toppers-jsp/blob/master/config/microblaze/cpu_support.S

```
/* 
 *
 *  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
 * 
 * 上記著作権者は，以下の (1)～(4) の条件か，Free Software Foundation 
 * によって公表されている GNU General Public License の Version 2 に記
 * 述されている条件を満たす場合に限り，本ソフトウェア（本ソフトウェア
 * を改変したものを含む．以下同じ）を使用・複製・改変・再配布（以下，
 * 利用と呼ぶ）することを無償で許諾する．
 * (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
 *     権表示，この利用条件および下記の無保証規定が，そのままの形でソー
 *     スコード中に含まれていること．
 * (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
 *     用できる形で再配布する場合には，再配布に伴うドキュメント（利用
 *     者マニュアルなど）に，上記の著作権表示，この利用条件および下記
 *     の無保証規定を掲載すること．
 * (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
 *     用できない形で再配布する場合には，次のいずれかの条件を満たすこ
 *     と．
 *   (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
 *       作権表示，この利用条件および下記の無保証規定を掲載すること．
 *   (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
 *       報告すること．
 * (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
 *     害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
 *
 * 本ソフトウェアは，無保証で提供されているものである．上記著作権者お
 * よびTOPPERSプロジェクトは，本ソフトウェアに関して，その適用可能性も
 * 含めて，いかなる保証も行わない．また，本ソフトウェアの利用により直
 * 接的または間接的に生じたいかなる損害に関しても，その責任を負わない．
 *
 *  @(#) $Id: cpu_support.S,v 1.15 2007/04/19 06:38:27 honda Exp $
 */

#define _MACRO_ONLY
        
/*
 *  アプリケーションと共通のインクルードファイル
 */
#include <kernel.h>
                
/*
 *  ターゲット依存情報の定義
 */
#include <t_config.h>

#include "jsp_kernel.h"
#include "offset.h"
#include <microblaze_asm.inc>
#include <microblaze.h>


/*
 * INTCの設計について，
 *
 *  保存するレジスタ
 *  R3-R4   Return Valus        (Volatile)
 *  R5-R10  Passing parameters  (Volatile)
 *  R11-R12 Temporaries         (Volatile)
 *  R14     Return address for interrupt
 *  R15     Return address for Sub-routine
 *  R16     Return address for Trap(Debugger)
 *  R17     Return address for Exeptions
 * ?R18     Reserved for Assember    
 */

#define STACK_TOP (STACKTOP - 0x4) 

#define INTC_ISR (INTC_BASE + INTC_INT_STATUS_REG)
#define INTC_IPR (INTC_BASE + INTC_INT_PENDING_REG)
#define INTC_IER (INTC_BASE + INTC_INT_ENABLE_REG)
#define INTC_IAR (INTC_BASE + INTC_INT_ACK_REG)
#define INTC_SIE (INTC_BASE + INTC_SET_INT_ENABLE)
#define INTC_CIE (INTC_BASE + INTC_CLEAR_INT_ENABLE)
#define INTC_IVR (INTC_BASE + INTC_INT_VECTOR_REG)
#define INTC_MER (INTC_BASE + INTC_MASTER_ENABLE_REG)


/*
 *  例外エントリ
 *  Not Support!
 */
	.text
	.globl exception_entry
	.align 2
exception_entry:
	nop
	



	.text
	.globl interrupt_entry
	.align 2
interrupt_entry:
/*
 * スタックポインタの切り替えが必要
 */
	addik r1,r1,-64
	swi r3,  r1, 60
	swi r4,  r1, 56
	swi r5,  r1, 52
	swi r6,  r1, 48
	swi r7,  r1, 44
	swi r8,  r1, 40
	swi r9,  r1, 36
	swi r10, r1, 32
	swi r11, r1, 28
	swi r12, r1, 24
	swi r14, r1, 20
	swi r15, r1, 16
	swi r16, r1, 12
	swi r17, r1, 8
	swi r18, r1, 4
	mfs r3,  rmsr     /* msrの保存 */
	swi r3,  r1, 0

	lwi   r5,  r13, interrupt_count
	bgti  r5,  nest_int      /* ネスト回数が1以上ならスタックを切り替えない */
	
	/*
	 * スタックポインタ切り替え
	 */
	la    r4,  r0, STACK_TOP   /* タスク独立部のスタックの読み込み */
	sw    r1,  r0, r4          /* タスクスタックの保存             */
	Mov   r1,  r4              /* スタックポインタ切り替え         */
nest_int:
	/* 
     * 割込みネスト回数のインクリメント
	 */
	addi  r5,  r5,  1 
	swi   r5,  r13, interrupt_count

	lwi   r3,  r0, INTC_IVR    /* ベクタの読み込み                 */
	add   r3,  r3, r3          /* ベクタを4倍                      */
	add   r3,  r3, r3	        
	lwi   r5,  r3, int_handler_table /* ハンドラアドレスの読み込み */
	lwi   r6,  r3, int_bit_table     /* マスクビットの読み込み     */
	swi   r6,  r0, INTC_CIE          /* 発生した割込みをマスク     */
	ori   r4,  r0, 0x02 | MSR_CACHE_SETTING /* r4 = 0x02           */
	Push  r6                         /* マスクビットをスタックに   */

	mts   rmsr,r4                    /* 割込み許可(MSR(IE)をセット)*/

	brald r15, r5             /* ハンドラ呼び出し */
	 nop

    la    r4, r0, MSR_CACHE_SETTING  
	mts   rmsr,r4                    /* 割込み禁止                 */

//    ori   r4,  r0, 0x03       /* r4 = 0x03                         */
//    swi   r4,  r0, INTC_MER   /* INTC_MER = 0x0 INTCスタート       */

	Pop   r6                         /* マスクビットの取り出し     */
//	swi   r6,  r0, INTC_IAR          /* ACK                        */        
	swi   r6,  r0, INTC_SIE          /* 発生割込みの許可           */

	/*
	 *  割込みネスト回数のデクリメント
     */
	lwi   r5,  r13, interrupt_count
	addi  r5,  r5,  -1 
	swi   r5,  r13, interrupt_count
	
	bgti  r5,  ret_to_task_int      /* ネスト回数が1以上なら戻る */

	lw    r1,  r0, r1	            /* スタックポインタを戻す    */  
	lwi   r4,  r13, reqflg          /* reqflg のチェック         */
	beqi  r4,  ret_to_task_int      /* FALSE なら タスクに戻る   */
	bri   ret_int                   /* TRUE なら ret_int に      */
ret_to_task_int:
	lwi  r3,  r1, 0
	mts  rmsr,r3
	lwi  r18, r1, 4
	lwi  r17, r1, 8
	lwi  r16, r1, 12
	lwi  r15, r1, 16
	lwi  r14, r1, 20
	lwi  r12, r1, 24
	lwi  r11, r1, 28
	lwi  r10, r1, 32
	lwi  r9,  r1, 36
	lwi  r8,  r1, 40
	lwi  r7,  r1, 44
	lwi  r6,  r1, 48
	lwi  r5,  r1, 52
	lwi  r4,  r1, 56
	lwi  r3,  r1, 60
	rtid r14,0 
	addik r1,r1,64



	/*
	 * 未登録の割込みが発生すると呼び出される
	 * Not Yet!
	 */
	.globl no_reg_interrupt
	.align 2
no_reg_interrupt:
	nop


	/*
	 * タスクディスパッチャ
	 * 
	 * dispatch は，interrupt_count = 0 
     * MSRの IE=0 の割込み禁止状態で呼び出さなければならない．
	 * exit_and_dispatch も同様に，interrupt_count = 0 割込み禁止状態で
     * 呼び出すのが原則であるが，カーネル起動時に対応するため，
     * interrupt_count = 1 で呼び出した場合にも対応している．
	 *    
	 */
	
	.globl dispatch
	.align  2
dispatch:
	addi  r1,  r1,  -64  /* スクラッチレジスタ以外を保存する */
	swi   r15, r1,  60
	mfs   r3,  rmsr      /* msrの保存(キャッシュの設定の保存) */
	swi   r3,  r1,  56                
	swi   r18, r1,  52   /* 必要か? */
	swi   r19, r1,  48
	swi   r20, r1,  44
	swi   r21, r1,  40
	swi   r22, r1,  36
	swi   r23, r1,  32
	swi   r24, r1,  28
	swi   r25, r1,  24
	swi   r26, r1,  20
	swi   r27, r1,  16
	swi   r28, r1,  12
	swi   r29, r1,  8
	swi   r30, r1,  4
	swi   r31, r1,  0
	lwi   r4 , r13, runtsk     /* r4 <- runtsk */
	swi   r1 , r4,  TCB_sp 	   /* タスクスタックをTCBに保存 */	
	la    r5 , r0,  dispatch_r /* 実行再開番地を保存 */
	swi   r5 , r4,  TCB_pc     /* 実行再開番地をTCBに保存   */
	bri   dispatcher

dispatch_r:
	lwi  r31,  r1, 0      /* レジスタを復帰 */
	lwi  r30,  r1, 4
	lwi  r29,  r1, 8
	lwi  r28,  r1, 12
	lwi  r27,  r1, 16
	lwi  r26,  r1, 20
	lwi  r25,  r1, 24
	lwi  r24,  r1, 28
	lwi  r23,  r1, 32
	lwi  r22,  r1, 36
	lwi  r21,  r1, 40
	lwi  r20,  r1, 44
	lwi  r19,  r1, 48
	lwi  r18,  r1, 52
    lwi  r3,   r1, 56   /* MSRを戻す(キャッシュの設定を戻す) */
    mts  rmsr,r3            
	addi r1,   r1, 60   /* スタックポインタを戻す */
	/*
	 *  タスク例外処理ルーチンの起動
	 *  dispatch_r は dispatcher から呼び出されるため，
	 *  tcb のアドレスは r4 に入っている
     *  Not Yet!
	 */
	lwi  r5,  r4,  TCB_enatex  /* r5 <- enatex                 */
	andi r6,  r5,  TCB_enatex_mask  
	beqi r6,  dispatch_r_1     /* enatex が FALSE ならリターン */
	lwi  r7,  r4,  TCB_texptn  /* r5 <- texptn                 */
	beqi r7,  dispatch_r_1     /* texptn が 0 でなければ       */
	brlid r15  call_texrtn     /* タスク例外ルーチンの呼び出し */	
	 nop
dispatch_r_1:
	Pop     r15
	rtsd	r15,8 
	 nop



	.globl exit_and_dispatch
exit_and_dispatch:
	/* interrupt_count をクリア */
	swi   r0,  r13, interrupt_count 
dispatcher:
	/*
	 * ここは割込み禁止で来ること
	 */
	lwi  r4,  r13, schedtsk  /* r4 <- schedtsk              */
	swi  r4,  r13, runtsk    /* schedtsk を runtsk に       */        
	beqi r4,  dispatcher_1   /* schedtsk があるか           */
	lwi  r1,  r4,  TCB_sp    /* TCBからタスクスタックを復帰 */
	lwi  r5,  r4,  TCB_pc    /* TCBから実行再開番地を復帰   */
	bra  r5	  
dispatcher_1:
	/*
	 * ここで割込みモードに切り替えるのは，ここで発生する割込み処理
     * にどのスタックを使うかという問題の解決と，割込みハンドラ内で
	 * のタスクディスパッチの防止という2つの意味がある．
	 */
	la   r1,  r0,  STACKTOP         /* 割込みスタックに変更             */
	la   r6,  r0,  1                /* interrupt_count を1に            */
	swi  r6,  r13, interrupt_count
	la   r5,  r0, 0x02 | MSR_CACHE_SETTING /* IE = '1'               */
	la   r4,  r0, MSR_CACHE_SETTING        /* IE = '0'               */        
dispatcher_2:
	mts   rmsr, r5   /* 割込み許可(MSR(IE)をセット)      */
	nop
	nop
	mts   rmsr, r4                  /* 割込み禁止(MSR(IE)をクリア)      */
	lwi   r6,  r13,  reqflg         /* r6 <- reqflg                     */
	beqi  r6,  dispatcher_2         /* reqflg が FALSE なら             */
	swi   r0,  r13, interrupt_count /* interrupt_count をクリア         */
	swi   r0,  r13,  reqflg         /* reqflg を FALSE に               */	
	bri   dispatcher

	/*
	 *  割込みハンドラ/CPU例外ハンドラ出口処理
	 * 
	 * 戻り先がタスクで reqflg がセットされている場合のみここにくる．
	 * interrupt_count = 0，割込み禁止状態，スクラッチレジスタを保存した
	 * 状態で呼び出すこと．
	 */
	.align 2
	.globl ret_int
	.globl ret_exc
ret_exc:
ret_int:
	swi  r0,  r13,  reqflg   /* reqflg を FALSE に */
	lwi  r4,  r13,  runtsk   /* r4 <- runtsk        */
	lwi  r6,  r13,  enadsp   /* r6 <- enadsp        */
	beqi r6,  ret_int_1      /* enadsp が FALSE なら ret_int_1 へ */
	lwi  r5,  r13,  schedtsk /* r5 <- schedtsk                    */
	sub  r6,  r5,   r4       /* runtsk と schedtsk が同じなら     */
	beqi r6,  ret_int_1      /* ret_int_1 へ                      */
	addi  r1,  r1,  -52      /* 残りのレジスタを保存する          */
	swi   r19, r1,  48
	swi   r20, r1,  44
	swi   r21, r1,  40
	swi   r22, r1,  36
	swi   r23, r1,  32
	swi   r24, r1,  28
	swi   r25, r1,  24
	swi   r26, r1,  20
	swi   r27, r1,  16
	swi   r28, r1,  12
	swi   r29, r1,  8
	swi   r30, r1,  4
	swi   r31, r1,  0	
	swi   r1 , r4,  TCB_sp 	   /* タスクスタックをTCBに保存 */	
	la    r6 , r0,  ret_int_r  /* 実行再開番地を保存 */
	swi   r6 , r4,  TCB_pc     /* 実行再開番地をTCBに保存   */
	bri   dispatcher

ret_int_r:	
	lwi  r31,  r1,  0      /* レジスタを復帰 */
	lwi  r30,  r1,  4
	lwi  r29,  r1,  8
	lwi  r28,  r1,  12
	lwi  r27,  r1,  16
	lwi  r26,  r1,  20
	lwi  r25,  r1,  24
	lwi  r24,  r1,  28
	lwi  r23,  r1,  32
	lwi  r22,  r1,  36
	lwi  r21,  r1,  40
	lwi  r20,  r1,  44
	lwi  r19,  r1,  48
	addi r1,   r1,  52
	lwi  r3,   r1,   0    /* MSR を戻す（キャッシュの設定を戻す）*/
	mts  rmsr, r3                
ret_int_1:
	/*
	 * タスク例外ルーチンの起動
	 * ret_int_r は dispatcher から呼び出されるため，
	 * tcb のアドレスは r4 に入っている
	 */
	lwi  r5,  r4,  TCB_enatex  /* r5 <- enatex                 */
	andi r6,  r5,  TCB_enatex_mask  
	beqi r6,  ret_int_2        /* enatex が FALSE ならリターン */
	lwi  r7,  r4,  TCB_texptn  /* r5 <- texptn                 */
	beqi r7,  ret_int_2        /* texptn が 0 でなければ       */
	brlid r15  call_texrtn     /* タスク例外ルーチンの呼び出し */	
	 nop
ret_int_2:
	lwi  r3,  r1, 0    /* MSR を戻す（割込みIE=0で割込み禁止になる）*/
	mts  rmsr,r3
	lwi  r18, r1, 4
	lwi  r17, r1, 8
	lwi  r16, r1, 12
	lwi  r15, r1, 16
	lwi  r14, r1, 20
	lwi  r12, r1, 24
	lwi  r11, r1, 28
	lwi  r10, r1, 32
	lwi  r9,  r1, 36
	lwi  r8,  r1, 40
	lwi  r7,  r1, 44
	lwi  r6,  r1, 48
	lwi  r5,  r1, 52
	lwi  r4,  r1, 56
	lwi  r3,  r1, 60
	rtid r14,0 
	 addik r1,r1,64	



	/*
	 * タスク起動処理
     *   
     *  スタックの取り方
     *  Microblaze Processor Reference Guide 52～53より
     *  関数呼出しのさい引数は，r5～r10 に格納する．
     *  それと同時に呼出し元はスタックフレームに引数の格納場所を確保する必要
     *  がある．さらにその上にはリンクレジスタ(R15)の分の領域が必要となる．
     *  呼出し先は更に他の関数を呼び出す場合等に r5～r10 をこの領域に保存す
     * る．
     *  Low Address
     *             --------------------
     *  new_sp -> | Link Register(R15) |
     *             --------------------
     *            |   Arg1用の領域     |
     *             --------------------
     *            |   Arg2用の領域     |
     *             --------------------        
     *            |      ....          |
     *             --------------------
     *  High Address
	 */

	.text
	.globl activate_r
	.align 2
activate_r:
	ori   r4,  r0, 0x02 | MSR_CACHE_SETTING  /* msrの初期値        */
	mts   rmsr,r4              /* 割込み許可(MSR(IE)をセット)      */
    lw    r11, r1, r0          /* タスクの実行番地                 */
    lwi   r5,  r1,  4          /* 引数（exinf）                    */
	la    r15, r0,  ext_tsk -8 /* タスクからの戻り先               */
	bra   r11                  /* タスクの実行開始                 */


        
    /*
     * 微少時間待ち
     */
     .globl _sil_dly_nse
_sil_dly_nse:
     addi   r5, r5, -SIL_DLY_TIM1
     bgti   r5, _sil_dly_nse_1
     rtsd   r15, 8
      nop  
_sil_dly_nse_1:
     addi   r5, r5, -SIL_DLY_TIM2
     bgti   r5, _sil_dly_nse_1
     rtsd   r15, 8
      nop          
```

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