中位PI C( 16F84) 留意点 Rev . 1. 0C‑01/06 HERO and heavy friends HERO and heavy friends 目 次 はじめに 3 ポ ート 初期化 条件分岐 テーブ ル処理 4 5 6 PC操作 8 演算 9 補数 バ イナリ加算 バ イナリ減算 バ イナリ乗算 バ イナリ除算 バ イナリ⇒パ ック化BCD変換 パ ック化BCD⇒バ イナリ変換 パ ック化BCD加算 パ ック化BCD減算 9 1 2 1 4 1 6 1 9 2 3 2 6 3 0 3 2 TMR0 の使用法 3 4 応用 3 6 入出力の拡張 RS‑232C 命令一覧表 2 7 ブ ロッ ク転送 PI C留意点 3 6 3 8 3 9 PI C留意点 ■ はじめに 本書のプ ログ ラム部分は、以下のシンボ ル定義済みとして記述しています。プ ログ ラム部分を利用する場合は、以下を ソース内に記述するか、以下を定義ファイルとして作成し、ソース内でインクルート ゙ してください。 . 1 6 f 8 4 ; PI C16F84に設定 W F E Q U E Q U 0 1 ; 作業レジ スタ ; ファイルレジ スタ I N D I R E C T I N D F R T C C T M R 0 O P T I O N R B P U I N T E D G R T S R T E P S A P S 2 P S 1 P S 0 E Q U E Q U E Q U E Q U E Q U E Q U E Q U E Q U E Q U E Q U E Q U E Q U E Q U 0 0 1 1 1 1 . 7 1 . 6 1 . 5 1 . 4 1 . 3 1 . 2 1 . 1 1 . 0 ; 0 0 :間接アト ゙ レッシング ; 0 0 : ; ( RTCC=TMR0=1) ; 0 1 :タイマデ ータ ; 8 1 :任意選択制御 ; O P T I O Nビ ット 7 ; O P T I O Nビ ット 6 ; O P T I O Nビ ット 5 ; O P T I O Nビ ット 4 ; O P T I O Nビ ット 3 ; O P T I O Nビ ット 2 ; O P T I O Nビ ット 1 ; O P T I O Nビ ット 0 P C P C L E Q U E Q U 2 2 ; =PCL ; 0 2 : 8 2 :プ ログ ラムカウンタ下位8ビ ット S T A T U S I R P R P 1 R P 0 T O P D Z D C C c E Q U E Q U E Q U E Q U E Q U E Q U E Q U E Q U E Q U E Q U 3 3 . 7 3 . 6 3 . 5 3 . 4 3 . 3 3 . 2 3 . 1 3 . 0 3 . 0 ; 0 3 : 8 3 :ステータス ; S T A T U Sビ ット 7i ndi r e c tpa g es e l e c t ; S T A T U Sビ ット 6pa g es e l e c t1 ; S T A T U Sビ ット 5pa g es e l e c t0 ; S T A T U Sビ ット 4t i meoutbi t ; S T A T U Sビ ット 3powe rdownbi t ; S T A T U Sビ ット 2z e r of l a g ; S T A T U Sビ ット 1di g i tc a r r y /bor r owf l a g ; S T A T U Sビ ット 0c a r r y /bor r owf l a g F S R P O R T A R A T R I S A r a E Q U E Q U E Q U E Q U E Q U 4 5 5 5 5 ; 0 4 : 8 4 :間接アト ゙ レスポ インタ ; 0 5 :ポ ート A( RA) ; 0 5 :ポ ート A( RA) ; 8 5 :ポ ート A方向レジ スタ P O R T B R B T R I S B r b E Q U E Q U E Q U E Q U 6 6 6 6 ; 0 6 :ポ ート B( RB) ; 0 6 :ポ ート B( RB) ; 8 6 :ポ ート B方向レジ スタ E E D A T A E E A D R E E C O N 1 E E I F W R E R R W R E N W R R D E E C O N 2 E Q U E Q U E Q U E Q U E Q U E Q U E Q U E Q U E Q U 8 9 8 8 . 4 8 . 3 8 . 2 8 . 1 8 . 0 9 ; 0 8 :EEPROMデ ータ ; 0 9 :EEPROMアト ゙ レス ; 8 8 :EEPROM制御1 ; 8 8 :EEPROM書き込み終了フラグ ; 8 8 :EEPROM書き込み打ち切りフラグ ; 8 8 :EEPROM書き込み許可フラグ ; 8 8 :EEPROM書き込み開始フラグ ; 8 8 :EEPROM読み出し開始フラグ ; 8 9 :EEPROM制御2 P C L A T H I N T C O N G I E E E I E T 0 I E I N T E R B I E T 0 I F I N T F R B I F E Q U E Q U E Q U E Q U E Q U E Q U E Q U E Q U E Q U E Q U 0 A H 0 B H 0 B H . 7 0 B H . 6 0 B H . 5 0 B H . 4 0 B H . 3 0 B H . 2 0 B H . 1 0 B H . 0 ; 0 A : 8 A :プ ログ ラムカウンタ上位 ; 0 B : 8 B :割り込み制御 ; I N T C O Nビ ット 7 ; I N T C O Nビ ット 6 ; I N T C O Nビ ット 5 ; I N T C O Nビ ット 4 ; I N T C O Nビ ット 3 ; I N T C O Nビ ット 2 ; I N T C O Nビ ット 1 ; I N T C O Nビ ット 0 HERO and heavy friends 3 HERO and heavy friends ■ 内蔵ポ ート 初期化 PI C内蔵のポ ート はビ ット 単位で入出力に設定可能です。通常、プ ログ ラム実行開始時に、入出力状態を決定するために ポ ート の初期化を行います。基本的な初期化手順を次に示します。 M O V L W M O V W F M O V L W M O V W F B S F M O V L W M O V W F M O V L W M O V W F C L R W D T M O V L W M O V W F B C F 0 0 0 1 1 1 0 0 b R A 0 0 0 0 0 1 0 0 b R B R P 0 0 0 0 0 0 0 0 1 b T R I S A 1 1 1 1 0 0 0 1 b T R I S B 0 0 0 0 1 0 0 1 b O P T I O N R P 0 ; RAビ ットデ ータをWに取得 ; RA=HHHLLに設定 ; RBビ ットデ ータをWに取得 ; RB= LLLLLHLLに設定 ; レジ スタファイル1に切換 ; RA方向ビ ットデ ータを設定 ; RA方向OOOOI に設定 ; RB方向ビ ットデ ータを設定 ; RB方向I I I I OOOI に設定 ; ウォッチト ゙ ッグタイマ初期化 ; OPTI ONビ ットデ ータを設定 ; プ ルアップ 有, ↓, 内部, ↑, WDT‑4分周 ; レジ スタファイル0に切換 ここでのポ イント はRA, RBの方向設定以前に出力デ ータを設定することです。この順ですと、出力ポ ート の初期値を確定す ることが可能です。 入出力Pi nの入出力決定条件は次の2点です。 ■ ポ ート 等価回路 ( 1ビ ット 分) ①リ セット 期間中は入力 Dn DQ Pi n ②リ セット 後のTRI Sレジ スタ値 ( 1=入力, 0=出力) ポ ート WR GQ リ セット 時のTRI Sレジ スタ( Q出力) 値は1( 入力) で、ポ ート レジ スタ値は不定です。 この場合、出力に設定するポ ート では、TRI Sレジ スタの該当するビ ット =0設定 DQ が行われるまで、対象ポ ート が入力であることに留意しなければなりません。 通常、出力Pi nが接続される回路の入力は、この期間の入力値を固定する TRI SWR GQ ため、抵抗によるプ ルアップ またはプ ルダ ウン処理を行います。 ポ ート RD この処理を行っても、リ セット 時に予期せぬ動作となる場合があります。その原因はポ ートデ ータの初期化とTRI Sレジ スタの 入出力設定の順序に起因します。 方向が出力に設定されると、入力( Hi ‑Z) から、出力ラッチの出力をPi nに出力するようになります。ポ ート デ ータの出力ラッチ の初期値は不定ですから、先にTRI Sレジ スタで入出力を設定すると、Pi n出力は不定となってしまいます。出力ポ ート の 出力デ ータラッチ自身は常に有効ですので、出力として使用するビ ット には、TRI Sレジ スタで方向を設定する前に、予め初 期値を設定しておきます。 ■ TRI S⇒ポ ートデ ータ順での初期化 出力Pi n値 Hi ‑Z 不定値 電源 MCLR TRI SWR ポ ートWR 通常、この後にRAMの内部変数などの初期化を行い、割り込みの初期化を行います。 4 PI C留意点 有効値 H L H L H L H L H L PI C留意点 ■ 条件分岐 PI Cには、多くのCPUに存在する条件分岐命令がありません。唯一、無条件分岐命令GOTOが存在するのみです。条 件分岐は、このGOTO命令と条件スキップ 命令を組み合わせて実現します。 中位PI Cには、条件スキップ 命令として次の命令があります。 B T F S S B T F S C D E C F S Z I N C F S Z f , b f , b f , d f , d ; f ( ファイル: RAM) のビ ット ( b) が1で次命令をスキップ ; f ( ファイル: RAM) のビ ット ( b) が0で次命令をスキップ ; f ( ファイル: RAM) を‑1し、結果が0でスキップ ; f ( ファイル: RAM) を+1し、結果が0でスキップ RAM上の1バ イト 長変数Xの値を検査し、0でラベ ルZEROへ分岐する例を次に示します。 M O V F B T F S C G O T O X , F Z Z E R O ; 変数Xの0検査 ; 0以外( Z=0) でスキップ ; 0( Z=1) で分岐 ; このように、多くのCPUで記述する分岐条件を含む分岐命令の形式ではなく、分岐条件の否定を含むスキップ 命令と無 条件分岐命令の組み合わせになりますので、スキップ 命令の条件記述には注意を要します。 このスキップ 命令を積極的に利用すると、2つの条件のOR条件分岐が短縮して記述可能です。次は、フラグ 変数FLGの ビ ット 0か4が1の場合に、ラベ ルACTへ分岐する単純な記述です。 B T F S C G O T O F L G , 0 A C T ; FLGのビ ット 0=0 でスキップ ; FLGのビ ット 0=1 でACTへ分岐 B T F S C G O T O F L G , 4 A C T ; FLGのビ ット 4=0 でスキップ ; FLGのビ ット 4=1 でACTへ分岐 ; ; 上記例は、次のように短縮して記述できます。 B T F S S B T F S C G O T O F L G , 0 F L G , 4 A C T ; FLGのビ ット 0=1 でスキップ ; FLGのビ ット 4=0 でスキップ ; FLGのビ ット 4, 0がともに1で分岐 ; 上記例のようなビ ット 単位の検査で3ビ ット 以上となる場合は、Wレジ スタを使用して一般の論理演算処理での分岐とする 方が命令語数、速度共に有利です。 M O V F A N D L W B T F S S G O T O F L G , W 0 1 0 1 0 1 0 1 b Z A C T ; FLG値をWに取得 ; ビ ット 6, 4, 2, 0のみ有効 ; ビ ット 6, 4, 2, 0が全て0でスキップ ; ビ ット 6, 4, 2, 0の何れかが1でACTへ分岐 ; 上記例は複数ビ ット のOR条件ですが、AND条件の場合は論理反転を行い、負論理AND( 正論理OR) で判定します。 M O V F X O R L W A N D L W B T F S C G O T O F L G , W 0 F F H 0 1 0 1 0 1 0 1 b Z A C T ; FLG値をWに取得 ; 論理反転( 負論理に変更) ; ビ ット 6, 4, 2, 0のみ有効 ; ビ ット 6, 4, 2, 0の何れかが1( 元値で0) でスキップ ; ビ ット 6, 4, 2, 0のすべてが0( 元値で1) でACTへ分岐 ; HERO and heavy friends 5 HERO and heavy friends ■ テーブ ル分岐 テーブ ル分岐のテーブ ル部分は無条件分岐命令GOTOを使用します。このテーブ ルを参照するには、テーブ ル番号をPCに加 算することで実現します。PCへの加算は、通常のバ イナリ 加算命令ADDWFを使用します。次にテーブ ル分岐の基本的な 例を示します。 T B N D S 1 ; 分岐テーブ ル番号変数定義 T B J M O V F A D D W F T B N , W P C ; テーブ ル番号をWに取得 ; プ ログ ラムカウンタを対応位置に変更 G O T O G O T O G O T O J O B 0 J O B 1 J O B 2 ; テーブ ル番号=0処理へ分岐 ; テーブ ル番号=1処理へ分岐 ; テーブ ル番号=2処理へ分岐 ① 〜 ; ①行実行時のPCは次の命令位置( 先頭のGOTO) を指しています。このPCにTBNを加算した値が新しいPCとなり、そ の位置から実行されます。PI Cでは全ての命令が1語長命令ですので、TBNの値はテーブ ルの番号( 位置) を示すことに なります。 ■ 定数テーブ ル 中位PI Cでは、その構造により、命令部とデ ータ部が明確に分離されています。このために、多くのCPUと同様な方法で 命令部に定数を定義することができません。PI Cで定数を定義するには、RETLW命令を使用します。次に定数テーブ ル の例を示します。 T B N D S 1 ; 定数テーブ ル番号変数定義 C T B M O V F A D D W F T B N , W P C ; テーブ ル番号をWに取得 ; プ ログ ラムカウンタを対応位置に変更 R E T L W R E T L W R E T L W 1 0 0 1 5 0 3 0 0 ; W=100、呼び出し元へ復帰 ; W=150、呼び出し元へ復帰 ; W=300、呼び出し元へ復帰 〜 ; 基本的な動作は上記のテーブ ル分岐と同じです。計算されたテーブ ルアト ゙ レスで実行されるRETLW命令が、Wレジ スタに定 数を設定し、呼び出し元へ復帰します。このルーチンを使用するには、予めTBNを設定し、CALL命令でCTBを呼び出し ます。戻り値( Wレジ スタ) が目的の定数になります。 ■ 制限事項 上記例の方法には重要な制限事項があります。PCLATHの操作が行われていない場合、テーブ ルの最後が00FFH以 下でなければいけません。PCLATHが操作されている場合は、PCLATHの値が上位アト ゙ レスとなる256語内にテーブ ルが 存在していなければなりません。 これはPI Cの構造上の制限で、GOTOやCALL命令のように命令語内に実質的なPCH( プ ログ ラムカウンタ上位) 値が存在 する場合には問題となりませんが、オペ ラント ゙ に直接PCを指定する一般命令によるPC操作の場合、PCHにはPCLATH の値が代入されることに起因します。 PC操作に関する詳細と解決法についてはPC操作を参照してください。 6 PI C留意点 PI C留意点 ■ PC操作 テーブ ル分岐や定数テーブ ルを使用する場合などに行われるPC操作では、PCH( プ ログ ラムカウンタ上位) の処理に注意しな ければいけません。これはPCの処理がGOTO命令やCALL命令の場合と異なるためです。 中位PI CのGOTO, CALL命令では、その命令語内に11ビ ット のPC値を保持しています。命令実行時には、この値がPC の下位11ビ ット になり、残りの上位ビ ット には、PCLATHの該当するビ ット 値が代入されます。 これはPCLATHのビ ット 4, 3がプ ログ ラムメモリ のバ ンク( ペ ージ ) レジ スタのような動作となることを意味します。但し、プ ログ ラム領 域が11ビ ット ( 2K語) 以下場合は、この動作を考慮せずに記述することができます。 ■ GOTO, CALL命令によるPC操作 PCH PCL 121110 9 8 7 6 5 4 3 2 1 0 GOTO, CALL命令 13121110 9 8 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 × × × × × × PCLATH 一般命令を使用したPC操作( 書き込み) では、その命令自体で扱われるデ ータは8ビ ット ですので、この8ビ ット デ ータがPCL になり、PCHにはPCLATHの下位5ビ ット が代入されます。 ■ 一般命令によるPC操作 PCH PCL ALUの値 121110 9 8 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 × × × PCLATH この場合、PC操作( 演算) によるキャリ ーやボ ローはPCHに反映されませんので、予めPCLATHを設定する記述が必要に なります。次にPCLに対する加算の場合の記述例を示します。 T B N D S 1 ; 分岐テーブ ル番号変数定義 T B J M O V L W M O V W F M O V L W A D D W F B T F S C I N C F T B L / 2 5 6 P C L A T H T B L T B N , W C P C L A T H , F ; テーブ ル基準アト ゙ レス上位をWに取得 ; PCLATHを仮設定 ; テーブ ル基準アト ゙ レス下位をWに取得 ; 対応テーブ ルアト ゙ レスをWに取得 ; キャリ ーなしでスキップ ; PCLATCH補正( +1) M O V W F P C ; プ ログ ラムカウンタを対応位置に変更 G O T O G O T O G O T O J O B 0 J O B 1 J O B 2 ; テーブ ル番号=0処理へ分岐 ; テーブ ル番号=1処理へ分岐 ; テーブ ル番号=2処理へ分岐 ; T B L 〜 ; この例では、テーブ ルの先頭アト ゙ レス上位をPCLATHに仮設定し、次にテーブ ルアト ゙ レス下位を加算によって計算して、その 結果のキャリ ーありでPCLATHを+1することで、PCへの書き込み時のPCLATHを予め設定しています。 テーブ ルが256境界内の場合は単純にPCLATHの設定だけの記述で済みます。また、プ ログ ラム領域が256未満( 0000〜 0 0FFH) の場合には、これらの考慮が不要です。 一般的に、テーブ ル記述は256未満のアト ゙ レスに記述するのが最良です。 HERO and heavy friends 7 HERO and heavy friends ■ ブ ロック転送 ブ ロック転送は間接ポ インタを利用します。間接ポ インタは1本しかありませんので、転送すべき変数領域間のオフセット 値を 加減算することで対処します。次にブ ロック転送ルーチンの例を示します。 C N T O F S T M P D S D S D S 1 1 1 ; 転送バ イト 数カウンタ変数定義 ; 転送先‑転送元オフセット 変数定義 ; 一時保存変数定義 B M V B M V 1 M O V W F M O V F M O V W F M O V F A D D W F M O V F M O V W F D E C F S U B W F D E C F S Z G O T O F S R I N D F , W T M P O F S , W F S R , F T M P , W I N D F O F S , W F S R , F C N T , F B M V 1 ; 転送元基準アト ゙ レスを間接ポ インタに設定 ; 転送元から1バ イト をWに取得 ; 転送元デ ータを一時保存 ; 転送先‑転送元オフセット をWに取得 ; 対応転送先アト ゙ レスを間接ポ インタに設定 ; 転送元デ ータをWに復帰 ; 転送元デ ータを転送先に設定 ; 転送先‑転送元オフセット ‑1をWに取得 ; 転送元間接ポ インタを進行/設定 ; 転送バ イト カウンタを減数, =0でスキップ ; 転送バ イト 数分継続 ① ; R E T U R N ; 呼出元へ復帰 次に本転送ルーチンの使用例を示します。この例では変数領域Xから変数領域Yへ8バ イト の転送を行っています。 D S D S 8 8 ; 変数領域X定義 ; 変数領域Y定義 ( Y ‑ X ) & 0 F F H O F S Y ‑ X C N T X B M V ; 転送先‑転送元オフセット をWに取得 ; 転送先‑転送元オフセット を設定 ; 転送バ イト 数をWに取得 ; 転送バ イト 数を設定 ; 転送元ポ インタをWに取得 ; ブ ロック転送 〜 X Y 〜 M O V L W M O V W F M O V L W M O V W F M O V L W C A L L この転送ルーチンでは領域の下位アト ゙ レス側から複写を行います。このため、転送元と転送先が重複し、且つ転送元が転 送先より下位側となる場合、内容が破壊されて正常な転送が行われませんので注意が必要です。 この場合は、転送ルーチンの①のDECFをI NCFに変更し、呼び出し時のWレジ スタに設定する転送元ポ インタを領域先頭 ではなく、領域最終位置とすることで対処できます。この変更によって領域の上位アト ゙ レス側から複写を行うようになりま す。但し、この場合は転送元が転送先より上位側となる場合に正常な転送ができなくなります。 すべての状態で正常な転送を行うようにするには方向フラグ 変数を定義し、①の位置でDECFかI NCFのどちらかを使 用する条件分岐の形式に変更します。とは言え、多くの場合、領域が重複し、且つ転送元と転送先の位置関係が両 方存在する場合は殆どないでしょう。また、そのような状態にならないような変数構成などを考慮すべきです。 次に転送バ イト 数と実行サイクル数の関係を示します。 ■ 命令語数と速度の関係 転送バ イト 数 命令語数 実行サイクル数 備考 2 24 実行命令サイクル数=転送バ イト 数×11+2 4 46 6 68 8 90 12 10 112 12 134 14 156 16 178 8 PI C留意点 PI C留意点 ■1 の補数 1の補数は単純に各ビ ット の論理反転値です。中位PI Cには1の補数を作成するCOMF命令があります。8ビ ット 長の1の 補数作成は、このCOMF命令で実現できます。 X D S 1 ; 1バ イト 長変数X定義 C O M F X , F ; 変数Xの1の補数作成 多倍長の場合は単純に連続的なCOMF命令で実現します。 X D S 3 ; 3バ イト 長変数X定義 C O M F C O M F C O M F X + 0 , F X + 1 , F X + 2 , F ; 変数X最下位バ イト の1の補数作成 ; 変数X第2バ イト の1の補数作成 ; 変数X最上位バ イト の1の補数作成 ■2 の補数 符号付き演算処理や減算を加算命令で行う場合などに、2の補数を作成する必要が生じます。中位PI Cには1の補数 ( ビ ット 反転) 作成のCOMF命令はありますが、2の補数を作成する命令がありません。このため、2の補数を作成するに はCOMF命令を利用して複数の命令で行います。 X D S 1 ; 1バ イト 長変数X定義 C O M F I N C F X , F X , F ; 変数Xの1の補数作成 ; 変数Xの2の補数作成 多倍長の場合は1の補数時と異なり、直前のバ イト からのキャリ ーを含めて処理しなければなりません。 X D S 2 ; 2バ イト 長変数X定義 C O M F I N C F X + 0 , F X + 0 , F ; 変数X最下位バ イト の1の補数作成 ; 変数X最下位バ イト の1の補数作成 B T F S C D E C F C O M F Z X + 1 , F X + 1 , F ; 最下位バ イト からのキャリ ーなしでスキップ ; キャリ ーで第2バ イト +1( 実際には次補数のため‑1) ; 変数X第2バ イト の2の補数作成 ; 第2バ イト 目以降は上記第2バ イト 処理と同様な形式で記述します。何れの場合もキャリ ーをZフラグ で判定( Z=1) している点 に注意してください。I NCF命令ではキャリ ーフラグ が無効なので、直前値+1がキャリ ーとなる場合に必ず結果が0になること を利用します。 ■ 命令語数と速度の関係 ビ ット 数 バ イト 数 命令語数 8 1 2 16 2 5 24 3 8 32 4 11 40 5 14 48 6 17 56 7 20 64 8 23 実行サイクル数 2 5 8 11 14 17 20 23 備考 HERO and heavy friends 9 HERO and heavy friends ■ ループ 処理による1の補数 多倍長もビ ット 数が多くなると命令語数的にループ 処理が有利です。 X C N T ; L O O P D S D S 4 1 ; 4バ イト 長変数X定義 ; 作業用カウンタ定義 M O V L W M O V W F M O V L W M O V W F X F S R 4 C N T ; 変数Xの基準ポ インタをWに取得 ; 変数Xの基準アト ゙ レスを間接ポ インタに設定 ; 変数Xのバ イト 数をWに取得 ; バ イトカウンタを初期化 C O M F I N C F D E C F S Z G O T O I N D F , F F S R , F C N T , F L O O P ; 対応バ イト の1の補数作成 ; 間接ポ インタを進行( +1) ; バ イトカウンタを減数、=0でスキップ ; 0以外でバ イト 数分処理継続へ 次に上記ループ 処理例と非ループ 処理( 必要数分のべた書き) での命令語数と実行サイクル数の関係を示します。 ■ 命令語数と速度の関係 命令語数 実行サイクル数 ビ ット 数 バ イト 数 非ループ ループ 非ループ ループ 8 1 1 1 8 16 2 2 2 13 24 3 3 3 18 32 4 4 4 23 8 40 5 5 5 28 48 6 6 6 33 56 7 7 7 38 64 8 8 8 43 命令語数が同一 備考 上記から64ビ ット ( 8バ イト ) 長を超える場合にループ 処理での命令語数の方が少なくなることが判ります。然しながら実行速 度は著しく遅くなり、同一命令語数となる64ビ ット 長の場合で5倍以上の速度低下になります。 とは言え、同一プ ログ ラム内で異なるビ ット ( バ イト ) 長のデ ータを扱う場合、上記例のFSRとCOUNTの設定だけ変更すれば 異なる長さの別デ ータが扱えますので、命令語数的にかなり有利となります。 10 PI C留意点 PI C留意点 ■ ループ 処理による2の補数 多倍長もビ ット 数が多くなると命令語数的にループ 処理が有利です。 X C N T ; L O O P D S D S 4 1 ; 4バ イト 長変数X定義 ; 作業用カウンタ定義 M O V L W M O V W F M O V L W M O V W F B S F X F S R 4 C N T Z ; 変数Xの基準ポ インタをWに取得 ; 変数Xの基準アト ゙ レスを間接ポ インタに設定 ; 変数Xのバ イト 数をWに取得 ; バ イトカウンタを初期化 ; 初回用にZフラグ を設定 B T F S C D E C F C O M F I N C F S Z D E C F S Z G O T O Z F S R , F F S R , F F S R , F C N T L O O P ; 前桁からのキャリ ーなしでスキップ ; キャリ ーで対応バ イト +1 ( 実際には次補数のため‑1) ; 対応バ イト の2の補数作成 ; 間接ポ インタを進行( +1) ; バ イトカウンタを減数、=0でスキップ ; 0以外でバ イト 数分処理継続へ 上記例の5行目のBSFは初回( 最下位バ イト ) 処理時に7行目のDECFを実行させるために必要です。この5行目のBSF の代わりに、GOTOで8行目のDECFへ分岐させても、結果は同じです。この場合の命令語数と実行サイクル数も同じで す。 10行目のI NCFSZをI NCFにしてはなりません。I NCF命令はZフラグ を更新します。このループ では9行目のCOMF命令の 結果のZフラグ を次回の7行目のBTFSCに引き継ぐ必要があります。I NCFSZ命令はフラグ を更新しません。 I NCFSZ命令でFSRが0となった場合にスキップ しますが、この場合のFSRは汎用レジ スタ( GPR) を指していますので、多く の場合、未実装領域となり、現実的にはほぼ有り得ません。 次に上記ループ 処理例と非ループ 処理( 必要数分のべた書き) での命令語数と実行サイクル数の関係を示します。 ■ 命令語数と速度の関係 命令語数 実行サイクル数 ビ ット 数 バ イト 数 非ループ ループ 非ループ ループ 8 1 2 2 11 16 2 5 5 18 24 3 8 8 25 32 4 11 11 32 命令語数が同一 11 40 5 14 14 39 48 6 17 17 46 56 7 20 20 53 64 8 23 23 60 備考 上記から32ビ ット ( 4バ イト ) 長を超える場合にループ 処理での命令語数の方が少なくなることが判ります。しかし、実行速度 は著しく遅くなり、同一命令語数となる32ビ ット 長の場合で3倍以上の速度低下になります。 とは言え、同一プ ログ ラム内で異なるビ ット ( バ イト ) 長のデ ータを扱う場合、上記例のFSRとCOUNTの設定のみ変更すれば 異なる長さの別デ ータが扱えますので、命令語数的にかなり有利となります。 HERO and heavy friends 11 HERO and heavy friends ■ バ イナリ加算 中位PI Cには8ビ ット ( 1バ イト ) 長の加算命令ADDWF命令があります。8ビ ット ( 1バ イト ) 長のバ イナリ 加算は、このADDWF命令 で実現できます。次は1バ イト 長のX=X+Yの例です。 X Y D S D S 1 1 ; 1バ イト 長変数X定義 ; 1バ イト 長変数Y定義 M O V F A D D W F Y , W X , F ; 変数Y( 加算値) をWに取得 ; 変数Xに変数Yを加算 多倍長の場合はADDWF命令の連続で処理しますが、直前のバ イト からのキャリ ーを含めて処理しなければなりません。 次は2 バ イト 長のX=X+Yの例です。 X Y D S D S 2 2 ; 2バ イト 長変数X定義 ; 2バ イト 長変数Y定義 M O V F A D D W F Y + 0 , W X + 0 , F ; 加算値最下位バ イト をWに取得 ; 最下位バ イト 加算 M O V F B T F S C I N C F S Z A D D W F Y + 1 , W C Y + 1 , W X + 1 , F ; 加算値第2バ イト をWに取得 ; 前桁からのキャリ ーなしでスキップ ; キャリ ーで加算値+1をWに取得, =0でスキップ ; 前桁からのキャリ ーなしか加算値+1≠0で第2バ イト 加算 ; 要点は5行目のBTFSCと6行目のI NCFSZで2重の条件分岐( スキップ ) を行っていることです。前桁からのキャリ ーなし時に は7行目のADDWFでの加算となり、キャリ ーあり時には加算値を+1することで前桁からのキャリ ーを反映しています。 更に、この加算値+1が0となる場合には7行目のADDWF命令をスキップ しています。これは次桁用にキャリ ーフラグ ( =1) を保 存するためです。加算値+1が0となる場合は今桁でキャリ ーが発生することを意味します。7行目のADDWF命令を実行 すると、今桁の結果は正しくなりますが、キャリ ーなし( C=0) になってしまいます。 この対処のために7行目のADDWF命令をスキップ する必要があります。直前のBTFSC命令の結果、I NCFSZ命令が実 行される場合のキャリ ーフラグ は常に1です。 第2バ イト 目以降は上記第2バ イト 処理と同様な形式で記述します。次にビ ット ( バ イト ) に対する命令語数と実行サイクル数の 関係を示します。 ■ 命令語数と速度の関係 ビ ット 数 バ イト 数 命令語数 8 1 2 16 2 6 24 3 10 32 4 14 40 5 18 48 6 22 56 7 26 64 8 30 12 PI C留意点 実行サイクル数 2 6 10 14 18 22 26 30 備考 PI C留意点 ■ ループ 処理によるバ イナリ加算 多倍長もビ ット 数が多くなると命令語数的にループ 処理が有利です。 X Y C N T T M P F L G ; L O O P D S D S D S D S D S 4 4 1 1 1 ; 4バ イト 長変数X定義 ; 4バ イト 長変数Y定義 ; 作業用カウンタ定義 ; 加算値一時保存変数定義 ; キャリ ーフラグ 一時保存変数定義 M O V L W M O V W F M O V L W M O V W F B C F X F S R 4 C N T C ; 変数Xの基準ポ インタをWに取得 ; 変数Xの基準アト ゙ レスを間接ポ インタに設定 ; 変数のバ イト 数をWに取得 ; バ イトカウンタを初期化 ; 初回用にキャリ ーフラグ をクリ ア R L F M O V L W A D D W F M O V F M O V W F M O V L W S U B W F M O V F B T F S C I N C F S Z A D D W F F L G , F Y ‑ X F S R , F I N D F , W T M P Y ‑ X F S R , F T M P , W F L G , 0 T M P , W I N D F , F ; 前桁からのキャリ ーフラグ を保存 ; 変数間オフセット をWに取得 ; 変数Yの対応バ イト のアト ゙ レスを間接ポ インタに設定 ; 加算値をWに取得 ; 加算値を一時保存 ; 変数間オフセット をWに取得 ; 変数Xの対応バ イト のアト ゙ レスを間接ポ インタに設定 ; 加算値をWに復帰 ; 前桁からのキャリ ーなしでスキップ ; キャリ ーで加算値+1をWに取得, =0でスキップ ; 前桁からのキャリ ーなしか加算値+1≠0で対応バ イト 加算 I N C F D E C F S Z G O T O F S R , F C N T , F L O O P ; 間接ポ インタを進行( +1) ; バ イトカウンタを減数、=0でスキップ ; 0以外でバ イト 数分処理継続へ ; 基本的には非ループ 処理の基本形と同じ方法ですが、ループ 処理を実現するために直接アト ゙ レッシング を行わず、間接アト ゙ レッシング によって変数アクセスを行っています。 間接アト ゙ レッシング 用のポ インタが1つだけですので、変数間オフセット の加減算で変数のポ インタを切り替えています。このた め、サブ ルーチン化して複数変数間で使用する場合は、対象となる変数間オフセット が同一でなければなりません。異なる 場合は8行目と12行目のMOVLW Y‑XをMOVFOFS, Wのように変数OFSから対応する変数間オフセット を取得するよう にし、呼び出しに先立ってこの変数OFSを設定します。 次に上記ループ 処理例と非ループ 処理( 必要数分のべた書き) での命令語数と実行サイクル数の関係を示します。 ■ 命令語数と速度の関係 命令語数 実行サイクル数 ビ ット 数 バ イト 数 備考 非ループ ループ 非ループ ループ 8 1 2 2 19 16 2 6 6 34 24 3 10 10 49 32 4 14 14 64 19 40 5 18 18 79 命令語数がほぼ同一 48 6 22 22 94 以降、ループ 処理の方が命令語数が少ない 56 7 26 26 109 64 8 30 30 124 上記から40ビ ット ( 5バ イト ) 長を超える場合にループ 処理での命令語数の方が少なくなることが判ります。けれども実行速 度は著しく遅くなり、ほぼ同一命令語数となる40ビ ット 長の場合で4倍以上の速度低下になります。 HERO and heavy friends 13 HERO and heavy friends ■ バ イナリ減算 中位PI Cには8ビ ット ( 1バ イト ) 長の減算命令SUBWF命令があります。8ビ ット ( 1バ イト ) 長のバ イナリ 減算は、このSUBWF命令 で実現できます。次は1バ イト 長のX=X‑Yの例です。 X Y D S D S 1 1 ; 1バ イト 長変数X定義 ; 1バ イト 長変数Y定義 M O V F S U B W F Y , W X , F ; 変数Y( 減算値) をWに取得 ; 変数Xから変数Yを減算 多倍長の場合はSUBWF命令の連続で処理しますが、直前のバ イト からのボ ローを含めて処理しなければなりません。 次は2 バ イト 長のX=X+Yの例です。 X Y D S D S 2 2 ; 2バ イト 長変数X定義 ; 2バ イト 長変数Y定義 M O V F S U B W F Y + 0 , W X + 0 , F ; 減算値最下位バ イト をWに取得 ; 最下位バ イト 減算 M O V F B T F S S I N C F S Z S U B W F Y + 1 , W C Y + 1 , W X + 1 , F ; 減算値第2バ イト をWに取得 ; 前桁からのボ ローなしでスキップ ; ボ ローで減算値+1をWに取得, =0でスキップ ; 前桁からのボ ローなしか減算値+1≠0で第2バ イト 減算 ; 減算での重要な点はボ ローフラグ です。ボ ローフラグ は物理位置的にキャリ ーフラグ と同一ですが、論理が異なります。この フラグ をボ ローとして扱う場合、負論理( 0=ボ ローあり、1=ボ ローなし) になります。 上例の要点は5行目のBTFSSと6行目のI NCFSZで2重の条件分岐( スキップ ) を行っていることです。前桁からのボ ローなし 時には7行目のSUBWFでの減算となり、ボ ローあり時には減算値を+1することで前桁からのボ ローを反映しています。 更に、この減算値+1が0となる場合には7行目のSUBWF命令をスキップ しています。これは、次桁用にボ ローフラグ ( Cフラグ =0) を保存するためです。減算値+1が0となる場合には今桁でボ ローが発生することを意味します。7行目のSUBWF命 令を実行すると、今桁の結果は正しくなりますが、ボ ローなし( Cフラグ =1) になってしまいます。 この対処のため、7行目のSUBWF命令をスキップ する必要があります。直前のBTFSS命令の結果、I NCFSZ命令が実行 される場合のボ ローフラグ は常に( Cフラグ =0) です。 第2バ イト 目以降は上記第2バ イト 処理と同様な形式で記述します。次にビ ット ( バ イト ) に対する命令語数と実行サイクル数の 関係を示します。 ■ 命令語数と速度の関係 ビ ット 数 バ イト 数 命令語数 8 1 2 16 2 6 24 3 10 32 4 14 40 5 18 48 6 22 56 7 26 64 8 30 14 PI C留意点 実行サイクル数 2 6 10 14 18 22 26 30 備考 PI C留意点 ■ ループ 処理によるバ イナリ減算 多倍長もビ ット 数が多くなると命令語数的にループ 処理が有利です。 X Y C N T T M P F L G ; L O O P D S D S D S D S D S 4 4 1 1 1 ; 4バ イト 長変数X定義 ; 4バ イト 長変数Y定義 ; 作業用カウンタ定義 ; 加算値一時保存変数定義 ; キャリ ーフラグ 一時保存変数定義 M O V L W M O V W F M O V L W M O V W F B S F X F S R 4 C N T C ; 変数Xの基準ポ インタをWに取得 ; 変数Xの基準アト ゙ レスを間接ポ インタに設定 ; 変数のバ イト 数をWに取得 ; バ イトカウンタを初期化 ; 初回用にボ ローフラグ をクリ ア R L F M O V L W A D D W F M O V F M O V W F M O V L W S U B W F M O V F B T F S S I N C F S Z S U B W F F L G , F Y ‑ X F S R , F I N D F , W T M P Y ‑ X F S R , F T M P , W F L G , 0 T M P , W I N D F , F ; 前桁からのボ ローフラグ を保存 ; 変数間オフセット をWに取得 ; 変数Yの対応バ イト のアト ゙ レスを間接ポ インタに設定 ; 減算値をWに取得 ; 減算値を一時保存 ; 変数間オフセット をWに取得 ; 変数Xの対応バ イト のアト ゙ レスを間接ポ インタに設定 ; 減算値をWに復帰 ; 前桁からのボ ローなしでスキップ ; ボ ローで減算値+1をWに取得, =0でスキップ ; 前桁からのボ ローなしか減算値+1≠0で対応バ イト 減算 I N C F D E C F S Z G O T O F S R , F C N T , F L O O P ; 間接ポ インタを進行( +1) ; バ イトカウンタを減数、=0でスキップ ; 0以外でバ イト 数分処理継続へ ; 基本的には非ループ 処理の基本形と同じ方法ですが、ループ 処理を実現するために直接アト ゙ レッシング を行わず、間接アト ゙ レッシング によって変数アクセスを行います。 間接アト ゙ レッシング 用のポ インタが1つだけですので、変数間オフセット の加減算で変数のポ インタを切り替えます。このため、 サブ ルーチン化して複数変数間で使用する場合は、対象となる変数間オフセット が同じでなければなりません。異なる場合 は8行目と12行目のMOVLW Y‑XをMOVFOFS, Wのように変数OFSから対応する変数間オフセット を取得するようにし、 呼び出しに先立ってこの変数OFSを設定します。 次に上記ループ 処理例と非ループ 処理( 必要数分のべた書き) での命令語数と実行サイクル数の関係を示します。 ■ 命令語数と速度の関係 命令語数 実行サイクル数 ビ ット 数 バ イト 数 備考 非ループ ループ 非ループ ループ 8 1 2 2 19 16 2 6 6 34 24 3 10 10 49 32 4 14 14 64 19 40 5 18 18 79 命令語数がほぼ同一 48 6 22 22 94 以降、ループ 処理の方が命令語数が少ない 56 7 26 26 109 64 8 30 30 124 上記から40ビ ット ( 5バ イト ) 長を超える場合にループ 処理での命令語数の方が少なくなることが判ります。けれども実行速 度は著しく遅くなり、ほぼ同一命令語数となる40ビ ット 長の場合で4倍以上の速度低下になります。 HERO and heavy friends 15 HERO and heavy friends ■ 加算によるバ イナリ乗算 中位PI Cには乗算命令がありませんので、加算命令ADDWFを基に作成します。基本的な方法は通常の筆算による 乗算と同一です。大きく異なるのは通常の10進数の場合、乗数の各桁計算時に非乗数×乗数の対応桁( 1桁) の乗算 がありますが、2進数の場合の1桁は0か1だけですので、0でそのまま、1で非乗数の加算になり、加算のみで行えるこ とです。 下図は8ビ ット ( 1バ イト ) 長のX×Y=Xの例です。結果のXは16ビ ット ( 2バ イト ) 長になります。例では中間結果を保持する作業 領域をXの上位に連結し、中間結果とXのビ ットシフト を同時に行っています。この手法により、作業領域が最小となり、 最終結果の移動もなくなります。また、各桁判定が常に変数Xの最下位ビ ット となり、その結果の桁単位の加算位置も 固定になりますので、ループ 処理に最適な方法です。 変数Xの上位は初期値として0を設定しておく必要があります。 151413121110 9 8 7 6 5 4 3 2 1 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 1 0 7 6 5 4 3 2 1 0 X Xの最下位ビ ット =0なので結果とXを1ビ ット 右シフト し、 最上位ビ ット =0とします。 1 1 0 0 0 1 00 0 15 Y 8 7 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 1 + Xのビ ット 1( 現在の最下位ビ ット ) =1なので、結果の対 応桁と Y を加算し 、 結果と X を1 ヒ ゙ ット 右シフト します。最 C ゙ ット は加算結果のキャリ ー( 例では0) です。 15 8 7 0 上位ヒ 0 1 1 0 0 0 1 0 0 0 0 0 0 1 1 0 1 7 0 1 1 0 0 0 1 00 15 0 8 7 0 0 1 1 0 0 0 1 0 0 0 0 0 0 1 1 0 15 8 7 0 0 0 1 1 0 0 0 1 0 0 0 0 0 0 1 1 + Xのビ ット 2( 現在の最下位ビ ット ) =0なので、結果とXを 1ビ ット 右シフト し、最上位ビ ット =0とします。 Xのビ ット 3( 現在の最下位ビ ット ) =1なので、結果の対 応桁とYを加算し、結果とXを1ビ ット 右シフト します。最 ゙ ット は加算結果のキャリ ー( 例では0) です。 15 8 7 0 上位ヒ 0 1 1 1 1 0 1 0 1 0 0 0 0 0 0 1 1 7 C 0 1 1 0 0 0 1 00 15 8 7 0 0 1 1 1 1 0 1 0 1 0 0 0 0 0 0 1 + Xのビ ット 4( 現在の最下位ビ ット ) =1なので、結果の対 応桁とYを加算し、結果とXを1ビ ット 右シフト します。最 ゙ ット は加算結果のキャリ ー( 例では1) です。 15 8 7 0 上位ヒ 1 0 0 1 1 1 1 1 0 1 0 0 0 0 0 0 1 7 C 15 0 0 0 0 1 1 0 0 0 1 00 8 7 0 1 0 0 1 1 1 1 1 0 1 0 0 0 0 0 0 15 8 7 0 0 1 0 0 1 1 1 1 1 0 1 0 0 0 0 0 15 8 7 0 0 0 1 0 0 1 1 1 1 1 0 1 0 0 0 0 15 8 7 0 0 0 0 1 0 0 1 1 1 1 1 0 1 0 0 0 Xのビ ット 5( 現在の最下位ビ ット ) =0なので、結果とXを 1ビ ット 右シフト し、最上位ビ ット =0とします。 Xのビ ット 6( 現在の最下位ビ ット ) =0なので、結果とXを 1ビ ット 右シフト し、最上位ビ ット =0とします。 Xの最上位ビ ット ( 現在の最下位ビ ット ) =0なので、結果 とXを1ビ ット 右シフト し、最上位ビ ット =0とします。 この方法は任意のバ イト 長乗算が可能です。次に任意のバ イト 長乗算作成時の要点を示します。 ① 変数Xの上位に連続して同一長の領域を確保します。 ② 上記領域は0で初期化します。 ③ 加算はバ イト 長分の多倍長加算で行います。 ④ 右シフト はバ イト 長分のRRF命令の連続で行います。 16 PI C留意点 PI C留意点 ■ バ イナリ乗算 中位PI Cには乗算命令がありませんので、加算命令ADDWFを基に作成します。次は16ビ ット ( 2バ イト ) 長のX×Y=X( 32 ビ ット ) の例です。 X Y C N T D S D S D S 2 + 2 2 1 ; 2+2バ イト 長変数X定義 ; 2バ イト 長変数Y定義 ; 作業用ビ ットカウンタ C L R F C L R F X + 2 + 0 X + 2 + 1 ; 結果上位を初期化 ; M O V L W M O V W F B C F B T F S S G O T O 1 6 C N T C X + 0 , 0 L P 1 ; ビ ット 数をWに取得 ; ビ ットカウンタを初期化 ; 対応桁キャリ ーなしを仮設定( キャリ ーフラグ をクリ ア) ; 変数Xの対応ビ ット =1でスキップ ; 変数Xの対応ビ ット =0で分岐 M O V F A D D W F Y + 0 , W X + 2 + 0 , F ; 乗数Y最下位バ イト をWに取得 ; 対応桁結果最下位バ イト 計算 M O V F B T F S C I N C F S Z A D D W F Y + 1 , W C Y + 1 , W X + 2 + 1 , F ; 乗数Y第2バ イト をWに取得 ; 前桁からのキャリ ーなしでスキップ ; キャリ ーで乗数第2バ イト 値+1をWに取得, =0でスキップ ; 前桁からのキャリ ーなしか第2バ イト 値+1≠0で第2バ イト 計算 R R F R R F R R F R R F X + 2 + 1 , F X + 2 + 0 , F X + 1 , F X + 0 , F ; 対応桁キャリ ー, 結果, 元デ ータX右シフト D E C F S Z G O T O C N T , F L O O P ; ビ ットカウンタ減数, =0でスキップ ; ≠0で、ビ ット 数分処理継続へ ; L O O P ; ; ; L P 1 ; ; ; 3バ イト 長以上の場合は1, 2行目の結果上位初期化部と18〜21行目の右シフト 部への追加、4行目のビ ット 数の変更、多 倍長加算の追加を行います。多倍長加算は17行目からへ13〜16行目の第2バ イト 加算と同様の形式で記述します。 ラベ ルLP1からのRRF命令は必ず上位側から記述しなければなりません。 次にビ ット ( バ イト ) 長に対する命令語数と実行サイクル数の関係を示します。 ■ 命令語数と速度の関係 ビ ット 数 バ イト 数 命令語数 8 1 12 16 2 19 24 3 26 32 4 33 40 5 40 48 6 47 56 7 54 64 8 61 実行サイクル数 74〜82 179〜259 316〜532 485〜901 686〜1366 919〜1927 1184〜2584 1481〜3337 備考 8×8=16ビ ット 16×16=32ビ ット 24×24=48ビ ット 32×32=64ビ ット 40×40=80ビ ット 48×48=96ビ ット 56×56=112ビ ット 64×64=128ビ ット HERO and heavy friends 17 HERO and heavy friends ■ 兼用型バ イナリ乗算 基本形を変形した兼用型バ イナリ 乗算ルーチンの例を次に示します。この例では8, 16, 24, 32ビ ット 長の乗算が行えます。但 し、各々の結果は8×8がX+3から、16×16がX+2から、24×24がX+1から、32×32がX+0からになります。 X Y C N T D S D S D S 4 + 4 4 1 ; 4+4バ イト 長変数X定義 ; 4バ イト 長変数Y定義 ; 作業用ビ ットカウンタ M U L 8 M O V L W G O T O 8 M U L ; ビ ット 数( =8) をWに取得 ; 実処理へ [ 8×8入口] M O V L W G O T O 1 6 M U L ; ビ ット 数( =16) をWに取得 ; 実処理へ [ 16×16入口] M O V L W G O T O 2 4 M U L ; ビ ット 数( =24) をWに取得 ; 実処理へ [ 24×24入口] M O V L W 3 2 ; ビ ット 数( =32) をWに取得 [ 32×32入口] C L R F C L R F C L R F C L R F X + 4 + 0 X + 4 + 1 X + 4 + 2 X + 4 + 3 ; 結果上位を初期化 ; ; ; M O V W F B C F B T F S S G O T O C N T C X + 0 , 0 M U L 2 ; ビ ットカウンタを初期化 ; 対応桁キャリ ーなしを仮設定( キャリ ーフラグ をクリ ア) ; 変数Xの対応ビ ット =1でスキップ ; 変数Xの対応ビ ット =0で分岐 M O V F A D D W F Y + 0 , W X + 4 + 0 , F ; 乗数Y最下位バ イト をWに取得 ; 対応桁結果最下位バ イト 計算 M O V F B T F S C I N C F S Z A D D W F Y + 1 , W C Y + 1 , W X + 4 + 1 , F ; 乗数Y第2バ イト をWに取得 ; 前桁からのキャリ ーなしでスキップ ; キャリ ーで乗数第2バ イト 値+1をWに取得, =0でスキップ ; 前桁からのキャリ ーなしか第2バ イト 値+1≠0で第2バ イト 計算 M O V F B T F S C I N C F S Z A D D W F Y + 2 , W C Y + 2 , W X + 4 + 2 , F ; 乗数Y第3バ イト をWに取得 ; 前桁からのキャリ ーなしでスキップ ; キャリ ーで乗数第3バ イト 値+1をWに取得, =0でスキップ ; 前桁からのキャリ ーなしか第3バ イト 値+1≠0で第3バ イト 計算 M O V F B T F S C I N C F S Z A D D W F Y + 3 , W C Y + 3 , W X + 4 + 3 , F ; 乗数Y第4バ イト をWに取得 ; 前桁からのキャリ ーなしでスキップ ; キャリ ーで乗数第4バ イト 値+1をWに取得, =0でスキップ ; 前桁からのキャリ ーなしか第4バ イト 値+1≠0で第4バ イト 計算 R R F R R F R R F R R F R R F R R F R R F R R F X + 4 + 3 , F X + 4 + 2 , F X + 4 + 1 , F X + 4 + 0 , F X + 3 , F X + 2 , F X + 1 , F X + 0 , F ; 対応桁キャリ ー, 結果, 元デ ータX右シフト ; ; ; ; ; ; ; D E C F S Z G O T O C N T , F M U L 1 ; ビ ットカウンタ減数, =0でスキップ ; ≠0で、ビ ット 数分処理継続へ ; M U L 1 6 ; M U L 2 4 ; M U L 3 2 ; M U L ; M U L 1 ; ; ; ; ; M U L 2 ; ; R E T U R N 18 PI C留意点 ; 呼び出し元へ復帰 PI C留意点 ■ 減算によるバ イナリ除算 中位PI Cには除算命令がありませんので減算命令SUBWFを基に作成します。基本的な方法は通常の筆算による除 算と同じです。大きく異なるのは通常の10進数の場合、除数の各桁計算時に非除数の対応桁÷除数の除算がありま すが、2進数の場合の1桁は0か1だけですので、0でそのまま、1で非除数の減算になり、減算のみで行えることです。 下図は8ビ ット ( 1バ イト ) 長のX÷Y=Xの例です。商は8ビ ット ( 1バ イト ) 長でX+0に、剰余も8ビ ット ( 1バ イト ) 長でX+1に格納されま す。例では中間結果を保持する作業領域をXの上位に連結し、中間結果とXのビ ットシフト を同時に行っています。この 手法によって作業領域が最小となり、最終結果の移動もなくなります。また、各桁での減算位置が常に固定となり、そ の結果の商ビ ット も常に変数Xの最下位ビ ット となりますので、ループ 処理に最適な方法です。 変数Xの上位は初期値として0を設定しておく必要があります。 キャリ ーフラグ は非除数ビ ット 数>除数ビ ット 数の場合のみ考慮しなければなりません。その他の場合のキャリ ーフラグ は常に0 となりますので、剰余−除数の対象にはなりません。 151413121110 9 8 7 6 5 4 3 2 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 7 6 5 4 3 2 1 0 X 0 0 0 1 1 0 1 0 Y 7 > C 15 8 7 0 左シフト 後、最上位桁減算不可なので、商の最上位 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 ビ ット =0を( 現在の商最下位ビ ット へ) 設定します。 0 0 0 0 1 1 0 1 0 C 0 C 0 C 0 C 0 C 0 15 8 7 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 15 8 7 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 15 8 7 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 15 8 7 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 15 8 7 左シフト後、上位2桁での減算不可なので、商の第 7ビ ット =0を( 現在の商最下位ビ ット へ) 設定します。 左シフト後、上位3桁での減算不可なので、商の第 6ビ ット =0を( 現在の商最下位ビ ット へ) 設定します。 左シフト後、上位4桁での減算不可なので、商の第 5ビ ット =0を( 現在の商最下位ビ ット へ) 設定します。 左シフト後、上位5桁での減算不可なので、商の第 4ビ ット =0を( 現在の商最下位ビ ット へ) 設定します。 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 ? − 左シフト 後、上位6桁での減算可なので減算を行い、 商の第3ビ ット =1を( 現在の商最下位ビ ット へ) 設定しま 15 8 7 0 す。 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 1 7 0 0 0 0 1 1 0 1 0 C 15 0 0 0 0 0 1 1 1 C 15 0 0 0 0 1 1 1 0 7 − 8 7 0 0 0 0 0 0 0 0 1 0 8 7 0 0 0 0 0 0 0 1 0 ? 0 0 0 0 1 1 0 1 0 15 左シフト後、上位7桁での減算不可なので、商の第 2ビ ット =0を( 現在の商最下位ビ ット へ) 設定します。 8 7 0 左シフト 後、上位8桁での減算可なので減算を行い、 商の最下位ビ ット =1を設定します。 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 1 剰余 商 この方法は任意のバ イト 長除算が可能です。次に任意のバ イト 長除算作成時の要点を示します。 ① 変数Xの上位に連続して同一長の領域を確保します。 ② 上記領域は0で初期化します。 ③ 減算はバ イト 長分の多倍長減算で行います。 ④ 左シフト はバ イト 長分のRLF命令の連続で行います。 HERO and heavy friends 19 HERO and heavy friends ■ バ イナリ除算 中位PI Cには除算命令がありませんので、減算命令SUBWFを基に作成します。次は16ビ ット ( 2バ イト ) 長のX÷Y=X( 16 ビ ット ) の例です。 X Y C N T D S D S D S 2 + 2 2 1 ; 2+2 バ イト 長変数X定義 ; 2バ イト 長変数Y定義 ; 作業用ビ ットカウンタ C L R F C L R F X + 2 + 0 X + 2 + 1 ; 非除数上位を初期化 ; M O V L W M O V W F B C F R L F R L F R L F R L F 1 6 C N T C X + 0 , F X + 1 , F X + 2 + 0 , F X + 2 + 1 , F ; ビ ット 数をWに取得 ; ビ ットカウンタを初期化 ; 商の対応ビ ット =0を仮設定 ; 非除数, 商を左シフト ( 桁移動) ; ; ; B T F S C G O T O C L P 2 ; 非除数対象最上位桁=0でスキップ ; 非除数対象最上位桁=1で減算へ M O V F S U B W F B T F S S G O T O Y + 1 , W X + 2 + 1 , W Z L P 1 ; 除数第2バ イト をWに取得 ; 第2 バ イト 減算可/不可検査 ; 同一値で下位桁検査へスキップ ; 可/ 不可判定可で分岐 M O V F S U B W F B T F S S G O T O Y + 0 , W X + 2 + 0 , W C L P 3 ; 除数最下位バ イト をWに取得 ; 最下位バ イト 減算可/不可検査 ; 減算可でスキップ ; 減算不可で分岐 B S F M O V F S U B W F X + 0 , 0 Y + 0 , W X + 2 + 0 , F ; 商の対応ビ ット =1を設定 ; 除数最下位バ イト をWに取得 ; 最下位バ イト 減算 M O V F B T F S S I N C F S Z S U B W F Y + 1 , W C Y + 1 , W X + 2 + 1 , F ; 除数第2バ イト をWに取得 ; 前桁からのボ ローなしでスキップ ; ボ ローで減数値+1をWに取得, =0でスキップ ; 第2 バ イト 減算 D E C F S Z G O T O C N T , F L O O P ; ビ ットカウンタ減数, =0でスキップ ; ≠0 で、ビ ット 数分処理継続へ ; L O O P ; ; ; ; 非除数ビ ット 数> (除数ヒ ゙ ット 数時必要) ; L P 1 ; L P 2 ; ; L P 3 3バ イト 長以上の場合は1, 2行目の非除数上位初期化部と7〜10行目の左シフト 部への追加、4行目のビ ット 数の変更、多 倍長比較と多倍長減算の追加を行います。多倍長比較は14行目からに15〜18行目の第2バ イト 比較と同様の形式で 記述し、多倍長減算は33行目からに29〜32行目の第2バ イト 減算と同様の形式で記述します。7行目からのRLF命令 は必ず下位側から記述しなければなりません。 次にビ ット ( バ イト ) 長に対する命令語数と実行サイクル数の関係を示します。 ■ 命令語数と速度の関係 ビ ット 数 バ イト 数 命令語数 8 1 15 16 2 26 24 3 37 32 4 48 40 5 59 48 6 60 56 7 71 64 8 82 20 PI C留意点 実行サイクル数 90〜106 259〜371 436〜796 645〜1381 886〜2126 1159〜3031 1464〜4096 1801〜5321 備考 8÷8=8ビ ット( 剰余=8ビ ット ) 16÷16=16ビ ット( 剰余=16ビ ット ) 24÷24=24ビ ット( 剰余=24ビ ット ) 32÷32=32ビ ット( 剰余=32ビ ット ) 40÷40=40ビ ット( 剰余=40ビ ット ) 48÷48=48ビ ット( 剰余=48ビ ット ) 56÷56=56ビ ット( 剰余=56ビ ット ) 64÷64=64ビ ット( 剰余=64ビ ット ) PI C留意点 ■ 兼用型バ イナリ除算 基本形を変形した兼用型バ イナリ 除算ルーチンの例を次に示します。この例では8〜64ビ ット 長の除算が行えます。結果は 商がX+0から、剰余がX+8からになります。但し、非除数Xの設定値は次表の位置から設定しなければなりません。 非除数Xビ ット 長 非除数X設定位置 8 X+7 16 X+6 24 X+5 32 X+4 40 X+3 48 X+2 56 X+1 64 X+0 備考 8÷8 16÷8 16÷ 16 24÷16 24÷24 32÷16 32÷32 40÷24 40÷32 48÷24 48÷32 56÷32 64÷32 X Y C N T D S D S D S 8 + 4 4 1 ; 8+4バ イト 長変数X定義 ; 4バ イト 長変数Y定義 ; 作業用ビ ットカウンタ D V 6 4 3 2 M O V L W G O T O 6 4 D I V 3 2 ; ビ ット 数( =64) をWに取得 ; 実処理へ [ 64÷32入口] M O V L W G O T O 5 6 D I V 3 2 ; ビ ット 数( =56) をWに取得 ; 実処理へ [ 56÷32入口] M O V L W G O T O 4 8 D I V 3 2 ; ビ ット 数( =48) をWに取得 ; 実処理へ [ 48÷32入口] M O V L W G O T O 4 8 D I V 2 4 ; ビ ット 数( =48) をWに取得 ; 実処理へ [ 48÷24入口] M O V L W G O T O 4 0 D I V 3 2 ; ビ ット 数( =40) をWに取得 ; 実処理へ [ 40÷32入口] M O V L W G O T O 4 0 D I V 2 4 ; ビ ット 数( =40) をWに取得 ; 実処理へ [ 40÷24入口] M O V L W G O T O 3 2 D I V 3 2 ; ビ ット 数( =32) をWに取得 ; 実処理へ [ 32÷32入口] M O V L W G O T O 3 2 D I V 1 6 ; ビ ット 数( =32) をWに取得 ; 実処理へ [ 32÷16入口] M O V L W G O T O 2 4 D I V 2 4 ; ビ ット 数( =24) をWに取得 ; 実処理へ [ 24÷24入口] M O V L W G O T O 2 4 D I V 1 6 ; ビ ット 数( =24) をWに取得 ; 実処理へ [ 24÷16入口] M O V L W G O T O 1 6 D I V 1 6 ; ビ ット 数( =16) をWに取得 ; 実処理へ [ 16÷16入口] M O V L W G O T O 1 6 D I V 8 ; ビ ット 数( =16) をWに取得 ; 実処理へ [ 16÷8入口] M O V L W 8 ; ビ ット 数( =8) をWに取得 [ 8÷8入口] C L R F C L R F C L R F C L R F C L R F C L R F C L R F M O V W F Y + 1 Y + 2 Y + 3 X + 8 + 0 X + 8 + 1 X + 8 + 2 X + 8 + 3 C N T ; 除数上位を初期化 ; ; ; 非除数( 仮想) 上位を初期化 ; ; ; ; ビ ットカウンタを初期化 ( 8ビ ット 除数移行点) ( 16ビ ット 除数移行点) ( 24ビ ット 除数移行点) ( 32ビ ット 除数移行点) ; D V 5 6 3 2 ; D V 4 8 3 2 ; D V 4 8 2 4 ; D V 4 0 3 2 ; D V 4 0 2 4 ; D V 3 2 3 2 ; D V 3 2 1 6 ; D V 2 4 2 4 ; D V 2 4 1 6 ; D V 1 6 1 6 ; D V 1 6 0 8 ; D V 0 8 0 8 ; D I V 8 D I V 1 6 D I V 2 4 D I V 3 2 ; 次頁へ続く HERO and heavy friends 21 HERO and heavy friends ; D I V 1 B C F R L F R L F R L F R L F R L F R L F R L F R L F R L F R L F R L F R L F C X + 0 , F X + 1 , F X + 2 , F X + 3 , F X + 4 , F X + 5 , F X + 6 , F X + 7 , F X + 8 + 0 , F X + 8 + 1 , F X + 8 + 2 , F X + 8 + 3 , F ; 商の対応ビ ット = 0を仮設定 ; 非除数, 商を左シフト ( 桁移動) ; ; ; ; ; ; ; ; 各桁減算( 剰余) 部左シフト ( 桁移動) ; ; ; B T F S C G O T O C D I V 3 ; 非除数対象最上位桁=0でスキップ ; 非除数対象最上位桁=1で減算へ M O V F S U B W F B T F S S G O T O Y + 3 , W X + 8 + 3 , W Z D I V 2 ; 除数第4バ イト をWに取得 ; 第4バ イト 減算可/不可検査 ; 同一値で下位桁検査へスキップ ; 可/不可判定可で分岐 M O V F S U B W F B T F S S G O T O Y + 2 , W X + 8 + 2 , W Z D I V 2 ; 除数第3バ イト をWに取得 ; 第3バ イト 減算可/不可検査 ; 同一値で下位桁検査へスキップ ; 可/不可判定可で分岐 M O V F S U B W F B T F S S G O T O Y + 1 , W X + 8 + 1 , W Z D I V 2 ; 除数第2バ イト をWに取得 ; 第2バ イト 減算可/不可検査 ; 同一値で下位桁検査へスキップ ; 可/不可判定可で分岐 M O V F S U B W F B T F S S G O T O Y + 0 , W X + 8 + 0 , W C D I V 4 ; 除数最下位バ イト をWに取得 ; 最下位バ イト 減算可/不可検査 ; 減算可でスキップ ; 減算不可で分岐 B S F M O V F S U B W F X + 0 , 0 Y + 0 , W X + 8 + 0 , F ; 商の対応ビ ット = 1を設定 ; 除数第1バ イト をWに取得 ; 第1バ イト 減算 M O V F B T F S S I N C F S Z S U B W F Y + 1 , W C Y + 1 , W X + 8 + 1 , F ; 除数第2バ イト をWに取得 ; 前桁からのボ ローなしでスキップ ; ボ ローで減数値+1をWに取得, =0でスキップ ; 前桁からのボ ローなしか減算値+1≠0で第2バ イト 減算 M O V F B T F S S I N C F S Z S U B W F Y + 2 , W C Y + 2 , W X + 8 + 2 , F ; 除数第3バ イト をWに取得 ; 前桁からのボ ローなしでスキップ ; ボ ローで減数値+1をWに取得, =0でスキップ ; 前桁からのボ ローなしか減算値+1≠0で第3バ イト 減算 M O V F B T F S S I N C F S Z S U B W F Y + 3 , W C Y + 3 , W X + 8 + 3 , F ; 除数第4バ イト をWに取得 ; 前桁からのボ ローなしでスキップ ; ボ ローで減数値+1をWに取得, =0でスキップ ; 前桁からのボ ローなしか減算値+1≠0で第4バ イト 減算 D E C F S Z G O T O C N T , F D I V 1 ; ビ ットカウンタ減数, =0でスキップ ; ≠0で、ビ ット 数分処理継続へ ; ; ; ; ; D I V 2 ; D I V 3 ; ; ; ; D I V 4 ; R E T U R N 22 PI C留意点 ; 呼び出し元へ復帰 PI C留意点 ■ バ イナリ⇒パ ック化BCD変換 8ビ ット 長バ イナリ ⇒パ ック化BCD変換の例を以下に示します。 X Y C N T 1 C N T 2 D S D S D S D S 1 2 1 1 ; バ イナリ 値( 元値) 変数定義 ; パ ック化BCD値( 変換値) 変数定義 ; バ イナリ 用ビ ットカウンタ定義 ; BCD用バ イトカウンタ定義 B 2 B C D C L R F C L R F M O V L W M O V W F G O T O Y + 0 Y + 1 8 C N T 1 B 2 D 3 ; 結果BCD変数を初期化 ; ; ビ ットカウンタを設定 ; ; 初回開始へ M O V L W M O V W F M O V L W M O V W F M O V L W A D D W F B T F S S S U B W F Y + 0 F S R 3 C N T 2 8 ‑ 1 0 / 2 I N D F , F I N D F , 3 I N D F , F ; BCD最下位バ イトポ インタをWに取得 ; BCD基準アト ゙ レスを間接ポ インタに設定 ; BCDバ イト 数をWに取得 ③ ; BCDバ イトカウンタを設定 ; 下桁で8‑次回1 0以上となる値( 5) を取得 ; 下桁次回10>か検査( 次桁LSB, 3ビ ット 補整) ; 下桁次回10以上でスキップ ; 次回9以下で元値復帰 M O V L W A D D W F B T F S S S U B W F ( 8 ‑ 1 0 / 2 ) * 1 6; 上桁で8‑次回1 0以上となる値( 5) を取得 I N D F , F ; 上桁次回10>か検査( 次桁LSB, 3ビ ット 補整) I N D F , 7 ; 上桁次回10以上でスキップ I N D F , F ; 次回9以下時、元値復帰 I N C F D E C F S Z G O T O F S R , F C N T 2 , F B 2 D 2 ; 間接ポ インタを進行 ; バ イトカウンタを減数, =0でスキップ ; BCDバ イト 数分継続 R L F R L F R L F D E C F S Z G O T O X + 0 , F Y + 0 , F Y + 1 , F C N T 1 , F B 2 D 1 ; バ イナリ 上位ビ ット から処理 ; バ イナリ 上位ビ ット をBCD最下位ビ ット へ ; ; ビ ット カウンタを減数, =0でスキップ ; ビ ット 数分継続 ; B 2 D 1 B 2 D 2 ① ② ; ; ; ④ ⑤ 上記例は変数定義と以下の点を変更することで、8ビ ット 長以外でも使用できます。 ① 結果BCD値のバ イト 数分を初期化します。 ② ビ ットカウンタ値はバ イナリ 値のビ ット 数を設定します。 ③ BCDバ イト 数は結果となるパ ック化BCDのバ イト 数を設定します。 ④ バ イナリ 値のバ イト 数分、下位バ イト からRLF命令を記述します。 ⑤ 結果BCD値バ イト 数分、下位バ イト からRLF命令を記述します。 バ イナリ 値のビ ット 長とBCD桁数、パ ック化BCDバ イト 数の関係を次に示します。 バ イナリビ ット 長 BCD桁数 パ ック化BCDバ イト 数 8 3 2 ■ 命令語数と速度の関係 ビ ット 数 バ イト 数 命令語数 8 1 25 16 2 28 24 3 31 32 4 34 40 5 39 48 6 42 56 7 45 64 8 48 16 5 3 実行サイクル数 240 717 1418 2343 4001 5478 7179 9104 24 8 4 32 10 5 40 13 7 48 15 8 56 17 9 64 20 10 備考 0〜 0〜 0〜 0〜 0〜 0〜 0〜 0〜 255 65535 16777215 4294967295 1099511627775 281474976710655 72057594037927935 18446744073709551615 HERO and heavy friends 23 HERO and heavy friends ■ 兼用型バ イナリ⇒パ ック化BCD変換 基本形を変形した兼用型バ イナリ ⇒パ ック化BCD変換ルーチンの例を次に示します。基本形に対し、既に終了( シフト ) した無 効なバ イナリ 値分の処理をバ イト 単位で行わないことで高速化を計っています。この手法で基本形に対して平均で2倍程 度速くなりますが、命令語数が増大します。また、バ イナリ 値によって実行速度が変化し、基本形に対して約1. 5〜3倍程 度の速度になります。 本例では8〜64ビ ット 長のバ イナリ ⇒パ ック化BCD変換が行えます。結果のパ ック化BCD値はY+0からになります。元値の バ イナリ 値は次表の位置から設定しなければなりません。 バ イナリ値ビ ット 長 バ イナリ値X設定位置 BCD桁数 パ ック化BCDバ イト 数 8 X+7 3 2 24 X+5 8 4 32 X+4 10 5 40 X+3 13 7 48 X+2 15 8 56 X+1 17 9 X Y C N T 1 C N T 2 T M P D S D S D S D S D S 8 1 0 1 1 1 ; バ イナリ 値( 元値) 変数定義 ; パ ック化BCD値( 変換値) 変数定義 ; バ イナリ 用ビ ットカウンタ定義 ; BCD用バ イトカウンタ定義 ; 処理BCDバ イト 数( 高速化用) B 2 D 8 M O V L W G O T O 8 B D 8 ; バ イナリビ ット 数( =8) をWに取得 ; 実処理へ [ 8ビ ットバ イナリ入口] M O V L W G O T O 1 6 B D 1 6 ; バ イナリビ ット 数( =16) をWに取得 ; 実処理へ [ 16ビ ットバ イナリ入口] M O V L W G O T O 2 4 B D 2 4 ; バ イナリビ ット 数( =24) をWに取得 ; 実処理へ [ 24ビ ットバ イナリ入口] M O V L W G O T O 3 2 B D 3 2 ; バ イナリビ ット 数( =32) をWに取得 ; 実処理へ [ 32ビ ットバ イナリ入口] M O V L W G O T O 4 0 B D 4 0 ; バ イナリビ ット 数( =40) をWに取得 ; 実処理へ [ 40ビ ットバ イナリ入口] M O V L W G O T O 4 8 B D 4 8 ; バ イナリビ ット 数( =48) をWに取得 ; 実処理へ [ 48ビ ットバ イナリ入口] M O V L W G O T O 5 6 B D 5 6 ; バ イナリビ ット 数( =56) をWに取得 ; 実処理へ [ 56ビ ットバ イナリ入口] M O V L W 6 4 ; バ イナリビ ット 数( =64) をWに取得 [ 64ビ ットバ イナリ入口] C L R F C L R F C L R F C L R F C L R F C L R F C L R F C L R F C L R F C L R F M O V W F M O V L W M O V W F G O T O Y + 9 Y + 8 Y + 7 Y + 6 Y + 5 Y + 4 Y + 3 Y + 2 Y + 1 Y + 0 C N T 1 1 T M P B 2 D 5 ; 結果BCD変数を初期化 ; ; ; ; ; ; ; ; ; ; ビ ットカウンタを設定 ; Wに1を取得 ; 処理BCDバ イト 数を初期化 ; 初回開始へ ; B 2 D 1 6 ; B 2 D 2 4 ; B 2 D 3 2 ; B 2 D 4 0 ; B 2 D 4 8 ; B 2 D 5 6 ; B 2 D 6 4 ; B D 6 4 B D 5 6 B D 4 8 B D 4 0 B D 3 2 B D 2 4 B D 1 6 B D 8 ; 次頁へ続く 24 16 X+6 5 3 PI C留意点 64 X+0 20 10 PI C留意点 ; B 2 D 1 B 2 D 2 M O V L W M O V W F M O V F M O V W F M O V L W A D D W F B T F S S S U B W F Y + 0 F S R T M P , W C N T 2 8 ‑ 1 0 / 2 I N D F , F I N D F , 3 I N D F , F ; BCD最下位バ イトポ インタをWに取得 ; BCD最下位バ イトアト ゙ レスを間接ポ インタに設定 ; 処理BCDバ イト 数をWに取得 ; BCDバ イトカウンタを設定 ; 下桁で8‑次回10以上となる値( 5) を取得 ; 下桁次回10>か検査( 次桁LSB, 3ビ ット 補整) ; 下桁次回10以上でスキップ ; 次回9以下で元値復帰 M O V L W A D D W F B T F S S S U B W F ( 8 ‑ 1 0 / 2 ) * 1 6; 上桁で8‑次回10以上となる値( 5) を取得 I N D F , F ; 上桁次回10>か検査( 次桁LSB, 3ビ ット 補整) I N D F , 7 ; 上桁次回10以上でスキップ I N D F , F ; 次回9以下で元値復帰 B T F S S G O T O I N D F , 7 B 2 D 3 ; 上桁次回10以上でスキップ ; 次回9以下で分岐 D E C F B T F S C I N C F G O T O C N T 2 , W Z T M P , F B 2 D 4 ; 最下位BCDバ イト か検査 ; 最下位バ イト 以外でスキップ ; 最下位バ イト で処理BCDバ イト 数を増加( +1) ; 次へ S U B W F I N D F , F ; 次回9以下時、元値復帰 I N C F D E C F S Z G O T O F S R , F C N T 2 , F B 2 D 2 ; 間接ポ インタを進行 ; バ イトカウンタを減数, =0でスキップ ; BCDバ イト 数分継続 R L F R L F R L F R L F R L F R L F R L F R L F R L F R L F R L F R L F R L F R L F R L F R L F R L F R L F D E C F S Z G O T O X + 0 , F X + 1 , F X + 2 , F X + 3 , F X + 4 , F X + 5 , F X + 6 , F X + 7 , F Y + 0 , F Y + 1 , F Y + 2 , F Y + 3 , F Y + 4 , F Y + 5 , F Y + 6 , F Y + 7 , F Y + 8 , F Y + 9 , F C N T 1 , F B 2 D 1 ; バ イナリ 上位ビ ット から処理 ; ; ; ; ; ; ; ; バ イナリ 上位ビ ット をBCD最下位ビ ット へ ; ; ; ; ; ; ; ; ; ; ビ ットカウンタを減数, =0でスキップ ; ビ ット 数分継続へ ; ; ; ; B 2 D 3 ; B 2 D 4 ; B 2 D 5 ; R E T U R N ; 呼出元へ復帰 HERO and heavy friends 25 HERO and heavy friends ■ パ ック化BCD⇒バ イナリ変換 パ ック化BCDをバ イナリ に変換するにはBCDの各桁のバ イナリ 値を加算します。BCDの各桁を下位桁からd1, d2, ・ ・ ・ とする と、n桁のBCD値は次式で表せます。 d1+d2×101+d3×102+・・・+dn×10n‑1 この式を変形すると次式になります。 d1+( d2+( d3+・・・dn×10・・・) ×10) ×10 この式からBCDの各桁毎に10倍と加算を行うことで変換できることが判ります。 次に4桁パ ック化BCD⇒16ビ ット 長バ イナリ 変換の例を示します。 X Y D S D S 2 + 2 2 ; バ イナリ 値( 変換値) +一時保存変数定義 ; パ ック化BCD値( 元値) 変数定義 D 2 B ; C L R F X + 1 ; 結果バ イナリ 変数を初期化 ① S W A P F A N D L W M O V W F C A L L M O V F C A L L S W A P F C A L L M O V F Y + 1 , W 0 F H X + 0 M 1 0 Y + 1 , W C 1 D Y , W C 1 D Y , W ; BCD最上位桁値をWに取得 ; 下位桁のみ有効 ; BCD最上位桁値設定 ; BCD最上位桁値を10倍 ; BCD第3桁値をWに取得 ; BCD第3桁値を積算後10倍 ; BCD第2桁値をWに取得 ; BCD第2桁値を積算後10倍 ; 最下位桁値をWに取得 ② ; (BCD1桁加算 ) A 1 D A N D L W A D D W F M O V L W B T F S C A D D W F R E T U R N 0 F H X + 0 , F 1 C X + 1 , F ; 下位桁のみ有効 ; 最下位バ イト に加算 ; Wに1を設定 ; キャリ ーなしでスキップ ; キャリ ーで第2バ イト +1 ; 呼出元へ復帰 ③ ③ ; (BCD1桁を加算後10倍 ) C 1 D ; M 1 0 C A L L A 1 D ; BCD1桁加算 B C F R L F R L F C X + 0 , F X + 1 , F ; キャリ ーフラグ を解除 ; 最下位バ イト ×2 ; 第2バ イト ×2 M O V F M O V W F M O V F M O V W F X + 0 , W X + 2 + 0 X + 1 , W X + 2 + 1 ; 最下位バ イト ×2 値をWに取得 ; 最下位バ イト ×2 値を一時保存 ; 第2バ イト ×2値をWに取得 ; 第2バ イト ×2値を一時保存 B C F R L F R L F C X + 0 , F X + 1 , F ; キャリ ーフラグ を解除 ; 最下位バ イト ×2 ( ×4) ; 第2バ イト ×2( ×4 ) ④ B C F R L F R L F C X + 0 , F X + 1 , F ; キャリ ーフラグ を解除 ; 最下位バ イト ×2 ( ×8) ; 第2バ イト ×2( ×8 ) ④ M O V F A D D W F X + 2 + 0 , W X + 0 , F ; 加算値最下位バ イト をWに取得 ; 最下位バ イト 加算 M O V F B T F S C I N C F S Z A D D W F X + 2 + 1 , W C X + 2 + 1 , W X + 1 , F ; 加算値第2バ イト をWに取得 ⑥ ; 前桁からのキャリ ーなしでスキップ ; キャリ ーで加数第2バ イト +1をWに取得, =0でスキップ ; 前桁or 第2バ イト +1のキャリ ーなしで第2バ イト 加算 ④ ; ⑤ ; ; ; ; ; R E T U R N 26 PI C留意点 ; 呼出元へ復帰 PI C留意点 前記の例は、変数と以下の点を変更することで、BCD4桁以外の桁数にも使用できます。 ① 結果バ イナリ 値バ イト 数‑1分、初期化します。 ② 同様の形式で必要なBCD桁数分を記述します。 ③ この2行と同様な形式で、結果バ イナリ 値のバ イト 数‑1分、加算処理を記述します。 ④ 必要なバ イナリ 値のバ イト 数分、下位バ イト からRLF命令を記述します。 ⑤ 結果バ イナリ 値バ イト 数分の一時保存処理を記述します。 ⑥ 同様な形式で、結果バ イナリ 値バ イト 数‑1分、加算処理を記述します。 バ イナリ 値のビ ット 長とBCD桁数、パ ック化BCDバ イト 数の関係を次に示します。 BCD桁数 パ ックト BCDバ イト 数 バ イナリビ ット 長 バ イナリバ イト 数 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 1 2 3 4 5 6 7 8 9 10 7 10 14 17 20 24 27 30 34 37 40 44 47 50 54 57 60 64 1 2 3 4 5 6 7 8 ■ 命令語数と速度の関係 BCD桁数 バ イナリバ イト 数 2 1 3 2 4 2 5 3 6 3 7 3 8 4 9 4 10 5 11 5 12 5 13 6 14 6 15 7 16 7 17 8 18 8 19 8 命令語数 19 37 41 57 61 65 81 85 101 105 109 121 125 141 145 161 165 169 実行サイクル数 23 68 101 179 223 267 389 444 599 665 731 930 1007 1239 1327 1592 1691 1790 備考 0〜 0〜 0〜 0〜 0〜 0〜 0〜 0〜 0〜 0〜 0〜 0〜 0〜 0〜 0〜 0〜 0〜 0〜 99 999 9999 99999 999999 9999999 99999999 999999999 9999999999 99999999999 999999999999 9999999999999 99999999999999 999999999999999 9999999999999999 99999999999999999 999999999999999999 9999999999999999999 HERO and heavy friends 27 HERO and heavy friends ■ 兼用型パ ック化BCD⇒バ イナリBCD変換 基本形を変形した兼用型パ ック化BCD⇒バ イナリ 変換ルーチンの例を次に示します。本例では2〜10桁( 1〜4バ イト ) のパ ック 化BCD⇒バ イナリ 変換が行えます。但し、結果のバ イナリ 値を最大4バ イト として扱っているため、10桁のパ ック化BCDの場 合の最大値は4294967295に制限されます。結果のバ イナリ 値はX+0からになります。元値のパ ック化BCD値はY+0が最 下位バ イト です。 BCD桁数 パ ック化BCDバ イト 数 バ イナリ値バ イト 数( ビ ット 長) 3 4 5 6 7 8 9 10 2 3 4 5 2( 10) 2( 14) 3( 17) 3( 20) 3( 24) 4( 27) 4( 30) 5( 34) X Y C N T D S D S D S 4 + 4 5 1 ; バ イナリ 値( 変換値) 変数/一時保存変数定義 ; パ ック化BCD値( 元値) 変数定義 ; パ ック化BCD桁数カウンタ定義 D 2 B 2 M O V L W G O T O 2 ‑ 1 D B 1 ; BCD桁数( =2) ‑ 1 をWに取得 ; バ イナリ 1バ イト 変換処理へ [ 2桁パ ック化BCD入口] M O V L W G O T O 3 ‑ 1 D B 2 ; BCD桁数( =3) ‑ 1 をWに取得 ; バ イナリ 2バ イト 変換処理へ [ 3桁パ ック化BCD入口] M O V L W G O T O 4 ‑ 1 D B 2 ; BCD桁数( =4) ‑ 1 をWに取得 ; バ イナリ 2バ イト 変換処理へ [ 4桁パ ック化BCD入口] M O V L W G O T O 5 ‑ 1 D B 3 ; BCD桁数( =5) ‑ 1 をWに取得 ; バ イナリ 3バ イト 変換処理へ [ 5桁パ ック化BCD入口] M O V L W G O T O 6 ‑ 1 D B 3 ; BCD桁数( =6) ‑ 1 をWに取得 ; バ イナリ 3バ イト 変換処理へ [ 6桁パ ック化BCD入口] M O V L W G O T O 7 ‑ 1 D B 3 ; BCD桁数( =7) ‑ 1 をWに取得 ; バ イナリ 3バ イト 変換処理へ [ 7桁パ ック化BCD入口] M O V L W G O T O 8 ‑ 1 D B 4 ; BCD桁数( =8) ‑ 1 をWに取得 ; バ イナリ 4バ イト 変換処理へ [ 8桁パ ック化BCD入口] M O V L W G O T O 9 ‑ 1 D B 4 ; BCD桁数( =9) ‑ 1 をWに取得 ; バ イナリ 4バ イト 変換処理へ [ 9桁パ ック化BCD入口] M O V L W 1 0 ‑ 1 ; BCD桁数( =10) ‑1をWに取得 [ 10桁パ ック化BCD入口] C L R F C L R F C L R F C L R F M O V W F A W K X + 3 A W K X + 2 A W K X + 1 A W K X + 0 C N T ; 結果バ イナリ 変数を初期化 ; ; ; ; BCD桁カウンタを設定 R R F C N T , W ; パ ック化BCD値バ イトオフセット をWに取得 A D D L W M O V W F M O V F B T F S C S W A P F Y F S R I N D F , W C N T , 0 I N D F , W ; パ ック化BCD対応バ イト 位置を取得 ; パ ック化BCD対応バ イト 用間接ポ インタ設定 ; 対応バ イト 下位桁をWに仮取得 ; 下位桁( =0) でスキップ ; 上位桁で対応バ イト 上位桁をW下位に取得 ; D 2 B 3 ; D 2 B 4 ; D 2 B 5 ; D 2 B 6 ; D 2 B 7 ; D 2 B 8 ; D 2 B 9 ; D 2 B 1 0 ; D B 4 D B 3 D B 2 D B 1 ; D 2 B 1 ; 次頁へ続く 28 2 1 1( 7) PI C留意点 PI C留意点 ; C A L L C A L L M O V F M O V W F M O V F M O V W F M O V F M O V W F M O V F M O V W F C A L L C A L L M O V F A D D W F A 1 D M 2 B X + 0 , W X + 4 X + 1 , W X + 5 X + 2 , W X + 6 X + 3 , W X + 7 M 2 B M 2 B X + 4 , W X + 0 , F ; BCD1桁加算 ; 現在のバ イナリ 値を2倍 ; 最下位バ イト ×2 値をWに取得 ; 最下位バ イト ×2 値を一時保存 ; 第2バ イト ×2値をWに取得 ; 第2バ イト ×2値を一時保存 ; 第3バ イト ×2値をWに取得 ; 第3バ イト ×2値を一時保存 ; 第4バ イト ×2値をWに取得 ; 第4バ イト ×2値を一時保存 ; 現在のバ イナリ 値を2倍( ×4) ; 現在のバ イナリ 値を2倍( ×8) ; 加算値最下位バ イト をWに取得 ; 最下位バ イト 加算 M O V F B T F S C I N C F S Z A D D W F X + 5 , W C X + 5 , W X + 1 , F ; 加算値第2バ イト をWに取得 ; 前桁からのキャリ ーなしでスキップ ; キャリ ーで加数第2バ イト +1をWに取得, =0でスキップ ; 前桁or 第2バ イト +1のキャリ ーなしで第2バ イト 加算 M O V F B T F S C I N C F S Z A D D W F X + 6 , W C X + 6 , W X + 2 , F ; 加算値第3バ イト をWに取得 ; 前桁からのキャリ ーなしでスキップ ; キャリ ーで加数第3バ イト +1をWに取得, =0でスキップ ; 前桁or 第3バ イト +1のキャリ ーなしで第3バ イト 加算 M O V F B T F S C I N C F S Z A D D W F X + 7 , W C X + 7 , W X + 3 , F ; 加算値第4バ イト をWに取得 ; 前桁からのキャリ ーなしでスキップ ; キャリ ーで加数第4バ イト +1をWに取得, =0でスキップ ; 前桁or 第4バ イト +1のキャリ ーなしで第4バ イト 加算 D E C F S Z G O T O C N T , F D 2 B 1 ; BCD桁カウンタを減数, =0でスキップ ; BCD桁数‑1分継続 M O V F Y + 0 , W ; BCD最下位バ イト をWに取得 ; ; ; ; ; (BCD1桁加算 ) A 1 D A N D L W A D D W F M O V L W B T F S C A D D W F B T F S C A D D W F B T F S C A D D W F R E T U R N ; (バ イナリ 値2倍 ) M 2 B B C F R L F R L F R L F R L F R E T U R N 0 F H X + 0 , F 1 C X + 1 , F C X + 2 , F C X + 3 , F C X + 0 , F X + 1 , F X + 2 , F X + 3 , F ; 下位桁( BCDの1桁) のみ有効 ; 結果バ イナリ の最下位バ イト に加算 ; Wに1を設定 ; キャリ ーなしでスキップ ; キャリ ーありで第2 バ イト に+1 ; キャリ ーなしでスキップ ; キャリ ーありで第3 バ イト に+1 ; キャリ ーなしでスキップ ; キャリ ーありで第4 バ イト に+1 ; 呼出元へ復帰 ; キャリ ーフラグ を解除 ; 結果バ イナリ の最下位バ イト ×2 ; 第2バ イト ×2 ; 第3バ イト ×2 ; 第4バ イト ×2 ; 呼出元へ復帰 HERO and heavy friends 29 HERO and heavy friends ■ パ ック化BCD加算 中位PI Cにはパ ック化BCD加算命令がありませんので8ビ ット ( 1バ イト ) 長のバ イナリ 加算命令ADDWF命令と桁キャリ ーフラグ を 利用して作成します。1バ イト 長のパ ック化BCD変数XとWレジ スタをパ ック化BCD加算する例( X+W=X) を以下に示します。 X F L G D S D S 1 1 ; 1バ イト 長パ ック化BCD変数X定義 ; パ ック化BCDキャリ ーフラグ 変数定義 P A D D A D D W F M O V F M O V W F X , F S T A T U S , W F L G ; バ イナリ 加算 ; フラグ をWに取得 ; フラグ を保存 M O V L W A D D W F B T F S C B S F 1 6 ‑ 1 0 X , F C F L G , 0 ; 加算で桁キャリ ーとなる値をWに取得 ; 下位桁9以下か検査( 下位桁補整) ; 下位桁補整でのバ イトキャリ ーなしでスキップ ; 下位桁補整でのバ イトキャリ ーで結果キャリ ー=1 B T F S C G O T O F L G , 1 P A D D 1 ; 以前のバ イナリ 加算での桁キャリ ーなしでスキップ ; バ イナリ 加算での桁キャリ ーで分岐 B T F S S S U B W F D C X , F ; 下位桁10以上でスキップ ; 下位桁9以下で元値復帰 M O V L W A D D W F B T F S C B S F ( 1 6 ‑ 1 0 ) * 1 6 X , F C F L G , 0 ; 加算でキャリ ーとなる値をWに取得 ; 上位桁9以下か検査 ; 上位桁9以下でスキップ ; 上位桁10以上で結果キャリ ーフラグ を設定 B T F S S S U B W F F L G , 0 X , F ; 最終的な上位桁からのキャリ ーありでスキップ ; キャリ ーなしで元値復帰 ; ; ; ; P A D D 1 ; ; 上記形式の連続で多倍長のパ ック化BCD加算が行えますが、命令語数的に不利です。通常、多倍長のパ ック化BCD 加算はループ 処理で記述します。ループ 処理形式では任意のバ イト 数のパ ック化BCDが扱え、実行速度は概ねバ イト 数に 比例します。 30 PI C留意点 PI C留意点 ■ ループ 処理によるパ ック化BCD加算 パ ック化BCD演算は桁当りの命令数が多いので、ループ 処理による演算が一般的です。次の例は任意のバ イト 数のパ ック 化BCD加算ルーチンです。このルーチンの呼び出し時にはWレジ スタにバ イト 数を設定する必要があります。 X Y C N T T M P F L G D S D S D S 1 〜 1 〜 1 D S 1 ; パ ック化BCD変数X定義 ; パ ック化BCD変数Y定義 ; バ イトカウンタ定義 ; 一時保存デ ータ( FLGと領域を共有) ; BCD最終桁からのキャリ ーフラグ 変数定義 P A D D M O V W F M O V L W M O V W F B C F M O V L W A D D W F M O V F B T F S C A D D L W C N T X F S R F L G , 0 Y ‑ X F S R , F I N D F , W F L G , 0 1 ; バ イトカウンタを設定 ; 変数X基準ポ インタをWに取得 ; 変数X基準位置を間接ポ インタに設定 ; 結果キャリ ーフラグ を初期化 ; 変数Yオフセット をWに取得 ; 対応変数Y位置を間接ポ インタに設定 ; 加算値をWに取得 ; 前回桁からのキャリ ーなしでスキップ ; キャリ ーありでBCD下位桁+1 M O V W F M O V L W S U B W F M O V F A D D W F M O V F M O V W F T M P Y ‑ X F S R , F T M P , W I N D F , F S T A T U S , W F L G ; 加算値を一時保存 ; 対応変数Xオフセット をWに取得 ; 対応変数X位置を間接ポ インタに設定 ; 加算値をWに復帰 ; バ イナリ 加算 ; フラグ をWに取得 ; フラグ を保存 M O V L W A D D W F B T F S C B S F 1 6 ‑ 1 0 I N D F , F C F L G , 0 ; 加算で桁キャリ ーとなる値をWに取得 ; 下位桁9以下か検査( 下位桁補整) ; 下位桁補整でのバ イトキャリ ー無しでスキップ ; 下位桁補整でのバ イトキャリ ーで結果キャリ ー=1 B T F S C G O T O F L G , 1 P A D D 2 ; 以前のバ イナリ 加算での桁キャリ ー検査 ; バ イナリ 加算での桁キャリ ーで分岐 B T F S S S U B W F D C I N D F , F ; 下位桁10以上9 でスキップ ; 下位桁9以下で元値復帰 M O V L W A D D W F B T F S C B S F ( 1 6 ‑ 1 0 ) * 1 6 I N D F , F C F L G , 0 ; 加算でキャリ ーとなる値をWに取得 ; 上位桁9以下か検査 ; 上位桁9以下でスキップ ; 上位桁10以上で結果キャリ ーフラグ を設定 B T F S S S U B W F F L G , 0 I N D F , F ; 最終的な上位桁からのキャリ ーありでスキップ ; キャリ ーなしで元値復帰 I N C F D E C F S Z G O T O F S R , F C N T , F P A D D 1 ; 間接ポ インタを進行 ; バ イトカウンタを減数, =0でスキップ ; バ イト 数分継続 P A D D 1 ; ; ; ; ; P A D D 2 ; ; ; R E T U R N ; 呼出元へ復帰 変数定義は必要とする最大バ イト 数を定義します。 次にパ ック化BCDの各バ イト 数に対する実行サイクル数の関係を示します。 ■ パ ック化BCD長と速度の関係 BCD桁数 BCDバ イト 数 命令語数 実行サイクル数 BCD桁数 BCDバ イト 数 1, 2 1 34〜 35 11, 12 6 3, 4 2 63〜 65 13, 14 7 5, 6 3 35 92〜 95 15, 16 8 7, 8 4 121〜 125 17, 18 9 9, 10 5 150〜 155 19, 20 10 HERO and heavy friends 命令語数 35 実行サイクル数 179〜 1 85 208〜 2 15 237〜 2 45 266〜 2 75 295〜 3 05 31 HERO and heavy friends ■ パ ック化BCD減算 中位PI Cにはパ ック化BCD減算命令がありませんので、8ビ ット ( 1バ イト ) 長のバ イナリ減算命令SUBWFと桁ボ ロー( キャリー) フラグ を利用して作成します。1バ イト 長のパ ック化BCD変数XからWレジ スタをパ ック化BCD減算し、結果を変数Xに格納す る例( X‑W=X) を以下に示します。 X F L G D S D S 1 1 ; 1バ イト 長パ ック化BCD変数X定義 ; パ ック化BCDボ ローフラグ 変数定義 P S U B S U B W F B S F R L F X , F F L G , 0 F L G , F ; バ イナリ 減算 ; 結果ボ ローフラグ を初期化 ; ボ ローフラグ を保存 M O V F B T F S C S U B L W X , W D C 9 ; バ イナリ 減算結果をWに取得 ; バ イナリ 減算の桁ボ ローでスキップ ; 下位桁9以下か検査 M O V L W B T F S S S U B W F 1 6 ‑ 1 0 D C X , F ; 下位桁補整値( =6) をWに取得 ; 9以下( 桁ボ ロー無し) でスキップ ; 下位桁9以下に補整 R R F M O V F B T F S C S U B L W B T F S C G O T O F L G , F X , W C 9 * 1 6 C P S U B 1 ; バ イナリ 減算でのボ ローフラグ を復帰 ; 下位桁補整後デ ータをWに取得 ; バ イナリ 減算でのボ ローでスキップ ; 上位桁9以下か検査 ; 10以上( ボ ロー) でスキップ ; 9以下で分岐 M O V L W S U B W F B C F ( 1 6 ‑ 1 0 ) * 1 6 ; 上位桁補整値( =60H) をWに取得 X , F ; 上位桁9以下に補整 F L G , 0 ; 結果ボ ローフラグ を設定 ; ; ; ; ; P S U B 1 ; 上記形式の連続で多倍長のパ ック化BCD減算が行えますが、命令語数的に不利です。通常、多倍長のパ ック化BCD 減算はループ 処理で記述します。ループ 処理形式では任意のバ イト 数のパ ック化BCDが扱え、実行速度は概ねバ イト 数に 比例します。 32 PI C留意点 PI C留意点 ■ ループ 処理によるパ ック化BCD減算 パ ック化BCD演算は桁当りの命令数が多いのでループ 処理による演算が一般的です。次の例は任意のバ イト 数のパ ック 化BCD減算ルーチンです。このルーチンの呼び出し時にはWレジ スタにバ イト 数を設定する必要があります。 X Y C N T T M P F L G D S D S D S 1 〜 1 〜 1 D S 1 ; パ ック化BCD変数X定義 ; パ ック化BCD変数Y定義 ; バ イトカウンタ定義 ; 一時保存デ ータ( FLGと領域を共有) ; BCD最終桁からのボ ローフラグ 変数定義 P S U B M O V W F M O V L W M O V W F B S F M O V L W A D D W F M O V F B T F S S A D D L W C N T X F S R F L G , 0 Y ‑ X F S R , F I N D F , W F L G , 0 1 ; バ イトカウンタを設定 ; 変数X基準ポ インタをWに取得 ; 変数X基準位置を間接ポ インタに設定 ; 結果ボ ローフラグ を初期化 ; 変数間オフセット をWに取得 ; 対応変数Y位置を間接ポ インタに設定 ; 減算値をWに取得 ; 前回桁からのボ ローなしでスキップ ; ボ ローありで減算値BCD下位桁+1 M O V W F M O V L W S U B W F M O V F S U B W F B S F R L F T M P Y ‑ X F S R , F T M P , W I N D F , F F L G , 0 F L G , F ; 減算値を一時保存 ; 変数間オフセット をWに取得 ; 対応変数X位置を間接ポ インタに設定 ; 減算値をWに復帰 ; バ イナリ 減算 ; 結果ボ ローフラグ を初期化 ; ボ ローフラグ を保存 M O V F B T F S C S U B L W I N D F , W D C 9 ; バ イナリ 減算結果をWに取得 ; バ イナリ 減算の桁ボ ローでスキップ ; 下位桁9以下か検査 M O V L W B T F S S S U B W F 1 6 ‑ 1 0 D C I N D F , F ; 下位桁補整値( =6) をWに取得 ; 9以下( 桁ボ ローなし) でスキップ ; 下位桁9以下に補整 R R F M O V F B T F S C S U B L W B T F S C G O T O F L G , F I N D F , W C 9 * 1 6 C P S U B 2 ; バ イナリ 減算でのボ ローフラグ を復帰 ; 下位桁補整後デ ータをWに取得 ; バ イナリ 減算でのボ ローでスキップ ; 上位桁9以下か検査 ; 10以上( ボ ロー) でスキップ ; 9以下で分岐 M O V L W S U B W F B C F ( 1 6 ‑ 1 0 ) * 1 6 ; 上位桁補整値( =60H) をWに取得 I N D F , F ; 上位桁9以下に補整 F L G , 0 ; 結果ボ ローフラグ を設定 I N C F D E C F S Z G O T O F S R , F C N T , F P S U B 1 P S U B 1 ; ; ; ; ; ; P S U B 2 ; 間接ポ インタを進行 ; バ イトカウンタを減数, =0でスキップ ; バ イト 数分継続 ; R E T U R N ; 呼出元へ復帰 変数定義は必要とする最大バ イト 数を定義します。 次にパ ック化BCDの各バ イト 数に対する実行サイクル数の関係を示します。 ■ パ ック化BCD長と速度の関係 BCD桁数 BCDバ イト 数 命令語数 実行サイクル数 BCD桁数 BCDバ イト 数 1, 2 1 34〜 36 11, 12 6 3, 4 2 63〜 67 13, 14 7 5, 6 3 35 92〜 98 15, 16 8 7, 8 4 121〜 129 17, 18 9 9, 10 5 150〜 160 19, 20 10 HERO and heavy friends 命令語数 35 実行サイクル数 179〜 1 91 208〜 2 22 237〜 2 53 266〜 2 84 295〜 3 15 33 HERO and heavy friends ■ TMR0の使用法 TMR0の使用で注意しなければいけないのは設定値です。基本的なことですが、TMR0は上昇カウンタで0FFHからの オーバ ーフローで割り込みが発生します。このため、設定値は256‑目的の計数値になります。実際のプ ログ ラム上では単に 目的の計数値に負符号を追加するだけです。例えば目的の計数値が16の場合、設定値は256‑16=240ですが、‑16と の記述は内部で0FFFFFFE0H( 32ビ ット 表現) になり、その下位8ビ ット が採用され、結果は0E0Hで10進数の240になりま す。 実際に注意が必要なのは同期化のための停止時間と割り込み応答時間です。これらによって結果的にタイマ間隔が長 くなる問題が発生します。特に前置分周器を有効( 2分周以上) にする場合は大変複雑になります。 次に前置分周器なしでの上記問題点を示すタイミ ング を示します。 ■ 前置分周器なしでの同期化遅延と割り込み応答遅延のタイミ ング 01230123012301230123012301230123012 FOSC 命令実行 TMR0値 命令 0FEH 命令 0FFH 命令 00H 命令 01H M O V W F T M R 0 02H 命令 n 命令 n 命令 n 命令 n+1 TOI F 割り込み応答遅延 割り込み処理 TMR0同期化遅延 この場合、TMR0同期化遅延の2サイクルと割り込み応答遅延の3サイクル分を目的計数値に対して補正すれば正確な タイマ周期が得られます。両方共に遅延要素ですので、実際の設定値は上記での設定値+5になります。上記例の16の 場合は5‑16のようになります。 現実には、この例の割り込み処理のようにいきなりTMR0書き込み命令となることはなく、レジ スタ保存やタイマ設定値の 取得命令などの後になります。その場合、それらの命令分の遅延が割り込み応答遅延に加算されます。これらを含め て最終的な設定値を求めます。 しかし、割り込み処理ルーチン先頭からTMR0書き込み命令間の命令実行サイクル数に応じて設定値を都度調整すること になり非常に不便です。また、2サイクル命令実行時に割り込みが発生した場合は割り込み応答遅延が+1されるので、こ の方法では常に正確なタイマ周期が得られません。これらを解決するにはTMR0に書き込む( MOVWFTMR0) のではな く、TMR0に加算する( ADDWFTMR0, F) 方法にします。TMR0オーバ ーフロー後、TMR0は継続して00Hからの上昇計数を 行っていますので、これはオーバ ーフロー後の経過サイクル数を表します。このため、補正値は常にTMR0同期化遅延の 2サイクル分だけになります。 この方法でも前置分周器を使用する場合は更に話が複雑になります。上記2項目の遅延自体は変わりませんが、 TMR0書き込み命令とTMR0計数クロック( 前置分周器出力) との同期化も行わなければなりません。TMR0書き込みによ って前置分周器がリセット されますので、TMR0書き込み命令はTMR0計数時と一致させる必要があります。ところが TMR0同期化遅延は常に2サイクルですので、実際にはTMR0計数時の2サイクル前で同期化を行わなければなりません。 前置分周器が2分周の場合はTMR0計数時と一致させ、設定値を+1することでも行なえます。 前置分周器が2分周で問題( 1サイクル誤差) となるタイミ ング 例を次に示します。 ■ 前置分周器が2分周での1サイクル誤差発生タイミ ング 01230123012301230123012301230123012 FOSC 命令実行 TMR0値 命令 0FEH 命令 0FFH 命令 命令 命令 00H A D D W F T M R 0 , F 01H 命令 n TOI F 割り込み応答遅延 34 PI C留意点 割り込み処理 TMR0同期化遅延 命令 n 命令 n PI C留意点 前置分周器が2分周時のTMR0書き込み命令とTMR0計数クロック( 前置分周器出力) との同期化プ ログ ラム例を次に示しま す。 S Y N C ; S Y N C 1 M O V F S U B W F B T F S C G O T O T M R 0 , W T M R 0 , W Z S Y N C 1 ; 現在のTMR0値をWに取得 ; このサイクルで計数か検査 ; このサイクルが計数でスキップ ; このサイクルが計数で分岐 M O V L W A D D W F 1 ‑ 1 6 T M R 0 , F ; ( 設定値‑TMR0 同期化遅延補正) 値をWに取得 ; TMR0再設定/ 補正 ( このサイクルが計数サイクル) この例ではTMR0同期化遅延の2サイクル分が2分周の1カウント に相当するので、設定値を‑1することで補正しています。4 分周以上では上記例のような簡単な記述では行なえず、かなり複雑になります。次に4分周時の例を示します。 S Y N C M O V F S U B W F B T F S S G O T O T M R 0 , W T M R 0 , W Z S Y N C 1 ; 現在のTMR0値をWに取得 ; このサイクルで計数か検査 ; 直前の命令サイクルが計数でなければスキップ ; 2つ前の命令サイクルが計数で分岐 N O P M O V F S U B W F B T F S S G O T O T M R 0 , W T M R 0 , W Z S Y N C 1 ; SUBWF命令間が4+1サイクルとなるための補正 ; 現在のTMR0値をWに取得 ; このサイクルで計数か検査 ; 直前の命令サイクルが計数でなければスキップ ; 2つ前の命令サイクルが計数で分岐 N O P M O V F S U B W F B T F S S G O T O T M R 0 , W T M R 0 , W Z S Y N C 1 ; SUBWF命令間が4+1サイクルとなるための補正 ; 現在のTMR0値をWに取得 ; このサイクルで計数か検査 ; 直前の命令サイクルが計数でなければスキップ ; 2つ前の命令サイクルが計数で分岐 ; ; ; N O P N O P ; S Y N C 1 N O P M O V L W A D D W F ; 最終同期位置用補正 ; ( 直前のGOTO S YNC1 より+1サイクルとなる補正) ‑ 1 6 T M R 0 , F ; 一致時のSUBWF命令からADDWF命令間サイクル数補正 ; ( 4の倍数‑TMR0同期化遅延の2サイクル) 正の最小値 ; TMR0再設定/ 補正 ( このサイクルが計数サイクル) この例では計数サイクルを検査するSUBWF命令間が4+1命令サイクルとなるようにしています。この計数サイクル検査を3回 行うことで計数サイクル位置を得ています。3回目で一致しなかった場合は次のサイクルが該当位置であることが分かって いますので、単にNOP命令でサイクル数調整を行っています。この例のMOVLWの取得値は負符号を付加した目的の 計数値そのものです。TMR0同期化遅延はプ ログ ラム実行サイクルで補正しています。 これ以上の分周値でも上記例と同様な手法で対応可能ですが、命令語数と実行時間からあまり実用的とは言えませ ん。むしろプ ログ ラムによるカウンタを併用し、TMR0自体はできるだけ前置分周器なしで使用する方が得策です。 何れの方法を採っても、割り込み発生時に実行中の命令の実行サイクルが1の場合と2の場合でTMR0と割り込み処理 ルーチン開始タイミ ング は1サイクルの誤差を生じますので、プ ログ ラムによるポ ート 出力などでのTMR0との同期化を完全/正確 に行うことは不可能です。 HERO and heavy friends 35 HERO and heavy friends ■ 入出力の拡張 入出力の拡張方法には多くの方法がありますが、ここでは一般的な同期シリ アル接続による方法を示します。パ ラレル接 続の方が速度的に有利ですが、内蔵ポ ート を大量に消費しますので得策ではありません。シリ アル接続で8ビ ット の入出力 処理を行う場合のプ ログ ラム実行時間は1 0MHz クロックで約50 μs 程度になります。 シリ アル接続の入力デ バ イスには74HC165, 166などが使用できます。出力には74HC595が最適です。また、特定メーカーで は74HC595ピ ン互換や機能相当で出力形態がバ イポ ーラTr やFET駆動の大電流ト ゙ ライバ となっているデ バ イスもあります ので、入手が可能ならば目的に応じて選択します。 次に74HC165と7 4HC595を使用する場合の例を示します。 74HC165 SI10 A 11 9 QH B 12 7 QH C 13 D 14 1S /L E3 F4 2 CK G 5 15 I H 6 NH SI STB CLK SO OE Vc c 74HC595 QA 15 QB 1 12 RCK QC 2 QD 3 11 S CK QE 4 10 S CLR QF 5 14 S I QG 6 QH 7 13 OE QH'9 入力00 入力01 入力02 入力03 入力04 入力05 入力06 入力07 出力10 出力11 出力12 出力13 出力14 出力15 出力16 出力17 c 74HC165 Vc SI A 入力10 QH B 入力11 QH C 入力12 D 入力13 S/L E 入力14 F 入力15 CK G 入力16 H I NH 入力17 Vc c 74HC595 QA QB RCK QC QD SCK QE SCLR QF SI QG QH OE QH' 出力00 出力01 出力02 出力03 出力04 出力05 出力06 出力07 上記例は入出力共に16ビ ット の拡張例です。この方法ではI C1個が8ビ ット 分ですので、8ビ ット 単位で任意の拡張ができ ます。3個目以降は2個目同様に縦列接続で結線します。 注意しなければならないのは順番で、図上のSI は左端のデ バ イスからの入力が先に入力され、SOは左端のデ バ イスが 最後の出力となることです。 上図では入力ポ ート のSI をQHに接続しています。これは入力が負論理入力の場合の接続方法で、正論理の場合は QH( 9番ピ ン) に接続します。このように入力の論理により論理を選択できる点で74HC165は74HC166より有利です。 この出力ポ ート の出力が出力ポ ート 初期化まで不定でもよい場合はOEをGNDに接続できます。また、出力ポ ート の初期 出力値がLならば、SCLRをリ セット 信号に接続することで、OEをGNDに接続できます。 PI C内蔵ポ ート の使用を少しでも減らしたい場合にはSI とSOを接続し、1ビ ット で処理することもできます。その場合のSI は 10k Ω程度の抵抗を介して接続します。プ ログ ラムでは方向レジ スタで内蔵ポ ート の該当ビ ット の方向を切り替えながら入出 力を行います。この方法では1つのシフトクロック内で入出力を同時に処理できず、入力と出力を個別に処理しなければ ならないので、入出力処理時間が入出力同時処理に比べて倍近くかかります。 36 PI C留意点 PI C留意点 ■ 拡張入出力制御 タイミ ング 図 前回値 CPU入力値 前回値 595出力値 165S/L 595RCK 165CLOCK 595SCK 165QH 595SI 今回値 今回値 ① ② t W1 t W2 1 2 3 4 5 6 7 8 t WC H G F E D C B A SI QHQGQFQEQDQCQBQA H 1 0 H 前回値 今回値 L ① ② H L t WS H 1 2 3 4 5 6 7 8 L H H G F E D C B A SI H L H QHQGQFQEQDQCQBQA L 前回値 今回値 ① 74HC165はS/L=L( 実際には立ち上がり) で165のA〜H入力をラッチします。②のタイミ ング で代用可能ですが、この場 合は前回の時点での入力状態になります。最新の状態を入力するためには①のタイミ ング で行います。同時に 74HC595でもシフトレジ スタ内のデ ータがラッチに取り込まれますが、シフトレジ スタの状態が変化していませんので、これ によって595の出力は変化しません。 ② 74HC595のRCKの立ち上がりで595のシフトレジ スタ値をラッチレジ スタにラッチします。この結果、595の各出力が同時に 変化します。同時に74HC165でもA〜H入力のラッチが行われます。①を行わない場合、これが165入力ラッチ動作に なります。 74HC16 5のCLOCKと74HC595のSCKはシフトレジ スタに対するシフトクロックで、共に立ち上がりでシフト 動作を行います。 ■ 拡張入出力初期化タイミ ング 図 CPU入力値 無効値 有効値 Hi ‑Z 595出力値 有効値 電源 PI CMCLR 595OE ① ② 165S/L 595RCK 165CLOCK 595SCK 1 0 H L H L H L H L H L H L ① リ セット 後のプ ログ ラム開始で通常のようにポ ート 初期化を行います。その後に接続した拡張入出力ビ ット の入出力処理 を行います( 上図例は8ビ ット 分) 。この時の出力デ ータが74HC595の初期値になります。また、入力デ ータも有効になり ます。 ② 74HC595のRCKの立ち上がりで595の内部レジ スタに指定値がラッチされますが、この時点での595出力端子は未だ Hi ‑Z状態です。この後に595のOEをLにすることで595出力端子が有効になります。 HERO and heavy friends 37 HERO and heavy friends ■I NT0, TMR0利用のRS‑232C PI C( 16F84) にはハート ゙ ウェアによるシリ アルインターフェース機能がありませんので、外部割込みとタイマを利用し、ソフト ウェアで実 現しますが、同時送受信は不可で交互双方向通信になります。 送信の場合、ビ ット 時間毎に出力信号( Tx D) を設定すればよいので、タイマの利用だけで実現できます。このタイマの設定 値は1ビ ット 時間です。 受信の場合は1バ イト 受信の起動となるスタートビ ット 開始の検出が必要です。具体的にはスタートビ ット の立ち上がりを外部 割込み( I NT0) で検出し、ビ ット 値採取用タイマを起動します。この立ち上がりは回線上での場合で、受信側にインバ ータが 存在する場合の入力信号( Rx D) では立ち下りになります。 ■ 送受信共にインバ ータを使用した場合の基本動作 t 2 I NT0割り込み ② t 1 TMR0割り込み Rx D( RB0) ① ST 0 1 2 3 4 5 6 7 SP Tx D( Rx n) ST 0 1 2 3 4 5 6 7 SP t 1:1 ビ ット 時間 t 2:1 /2ビ ット 時間 :ヒ ゙ ット 値採取 :出力 H L H L ST:スタートヒ ゙ ット SP:スト ップビ ット ①I NT0割り込みでTMR0の計数値を1/2ビ ット 時間に設定します。設定後、必ずTMR0割り込み要求フラグ ( T0I F) をクリ ア します。以降のTMR0割り込みでは計数値を1ビ ット 時間に設定します。 ② スタートビ ット 開始後にも殆どの場合、I NT0割り込みが発生します。これらのI NT0割り込みは1バ イト 受信完了までI NT0 割り込みを禁止するか、または無視する必要があります。 TMR0の計数値は基本的に1/2または1ビ ット 時間ですが、実際には割り込み応答時間を考慮する必要があります。 送信時は各ビ ット 出力処理間の最大誤差が実際の出力信号での誤差となりますが、通常、この差はプ ログ ラム数ステップ 分程度ですので、転送レート が低い場合は無視できる値です。 受信時の各ビ ット 受信処理も同様ですが、全体の基準となるI NT0割り込みでのTMR0計数値への1/2ビ ット 時間設定は 厳密さが要求されます。 ■ 上記基本動作でのI NT0割り込み時詳細 I NT0割り込み TMR0値設定 ① I NT0処理 t I t C TMR0処理 その他処理 ③ スタートビ ット 中央 t C+ t S ② t S Rx D( RB0) t C:PI C固有割り込み応答時間 t T t I :I NT0応答時間 1/2ビ ット 時間 スタートビ ット t S:TMR0採取応答時間 t T:TMR0設定応答時間 H L ①I NT0入力の有効エッジ から割り込み処理ルーチンが起動されるまでに( 1または2) +3サイクル( ×4クロック) の遅延( t C) があり ます。 ② スタートビ ット 検出のTMR0割り込みはt C+ t S分の遅延が存在するため、③位置で発生させなければなりません。また、 TMR0計数値設定時までにt C+ t I 分の遅延もあります。 これらのため、②での設定値は1/2ビ ット 時間‑( t C+ t I ) ‑( t C+ t S) になります。同様にTMR0割り込みでの1ビ ット 時間も 1ビ ット 時間‑( t C+ t T) にしなければなりません。 その他の割り込み処理がI NT0やTMR0と非同期に発生する場合、その他の割り込み処理中にI NT0やTMR0割り込み を検査し、これらの割り込みがある場合にその処理を優先するなどの処置をすることで、t I , t S, t Tなどの応答時間を一 定とする工夫が必要です。 同様にプ ログ ラム内で割り込み禁止期間が存在すると、その期間分t Cに対する誤差要因となり、全体に影響を及ぼしま す。原則的に割り込み禁止の使用は不可としてプ ログ ラミ ング します。 38 PI C留意点 PI C留意点 ■ 命令一覧表 ニーモニック/オペ ラント ゙ A D D W F A N D W F C L R F C L R W C O M F D E C F D E C F S Z I N C F I N C F S Z I O R W F M O V F M O V W F N O P R L F R R F S U B W F S W A P F X O R W F f , d f , d f f , d f , d f , d f , d f , d f , d f , d f f , d f , d f , d f , d f , d 意味 サイクル数 14ビ ットオペ コート ゙ バ イト 単位のファイルレジ スタ命令 AddW a ndf 1 000111dfffffff ANDW wi t hf 1 000101dfffffff Cl e a rf 1 0000011fffffff Cl e a rW 1 0000010xxxxxxx Compl e me ntf 1 001001dfffffff De c r e me ntf 1 000011dfffffff De c r e me ntf ,Sk i pi f0 1 /2 001011dfffffff I nc r e me ntf 1 001010dfffffff I nc r e me ntf ,Sk i pi f0 1 /2 001111dfffffff I nc l us i v eORW wi t hf 1 000100dfffffff Mov ef 1 001000dfffffff Mov eW t of 1 0000001fffffff NoOpe r a t i on 1 0000000xx 00000 Rot a t eLe f tft hr oug hCa r r y 1 001101dfffffff Rot a t eRi g htft hr oug hCa r r y 1 001100dfffffff Subt r a c tW f r omf 1 000010dfffffff Swa pni bbl e si nf 1 001110dfffffff Ex c l us i v eORW wi t hf 1 000110dfffffff 更新ステータス Z,DC,C Z Z Z Z Z Z Z Z C C Z,DC,C Z 注意 1,2 1,2 2 1,2 1,2 1,2,3 1,2 1,2,3 1,2 1,2 1,2 1,2 1,2 1,2 1,2 ビ ット 単位のファイルレジ スタ命令 B C F B S F B T F S C B T F S S f , b f , b f , b f , b Bi tCl e a rf Bi tSe tf Bi tTe s tf ,Sk i pi fCl e a r Bi tTe s tf ,Sk i pi fSe t 1 1 1 /2 1 /2 0100bbbfffffff 0101bbbfffffff 0110bbbfffffff 0111bbbfffffff 1,2 1,2 3 3 リテラル、制御命令 A D D L W A N D L W C A L L C L R W D T G O T O I O R L W M O V L W R E T F I E R E T L W R E T U R N S L E E P S U B L W X O R L W シンボ ル b d f k W x k k k k k k k k k Addl i t e r a la ndW ANDl i t e r a lwi t hW Ca l ls ubr out i ne Cl e a rWa t c hdogTi me r Got oa ddr e s s I nc l us i v eORl i t e r a lwi t hW Mov el i t e r a lt oW Re t ur nf r omi nt e r r upt Re t ur nwi t hl i t e r a li nW Re t ur nf r omSubr out i ne Goi nt os t a ndbymode Subt r a c tW f r oml i t e r a l Ex c l us i v eORl i t e r a lwi t hW 1 1 2 1 2 1 1 2 2 2 1 1 1 11111xkkkkkkkk 1110 01kkkkkkkk 100kkkkkkkkkkk 00000001100100 101kkkkkkkkkkk 111000kkkkkkkk 1100 xxkkkkkkkk 00000000001001 1101xxkkkkkkkk 00000000001000 00000001100011 11110xkkkkkkkk 111010kkkkkkkk Z,DC,C Z TO,PD Z TO,PD Z,DC,C Z 意味 8ビ ットファイルレジ スタ内のビ ットアト ゙ レス 結果格納先指定子;d=0( 結果はWに格納) 、d=1( 結果はf( ファイルレジ スタ) に格納) ファイルレジ スタのアト ゙ レス( 00H〜 7FH) リ テラル、定数デ ータまたはラベ ル 作業レジ スタ( 累積器) 無効 ( 0または1) 注意:1.I /Oレジ スタに対するRe a dmodi f yWr i t e ( MOVFRB, Fなど) はピ ンの入力レベ ルが使用されます。例えば入力ピ ンのデ ータ ラッチが1、そのピ ンが外部デ バ イスによりLowレベ ルとなっている場合、デ ータラッチには0が書き込まれます。 2.前置分周器がTMR0に割り当てられている場合、これらの命令をTMR0レジ スタに対して実行すると( TMR0に対して書 き込みを伴う場合) 、TMR0部に割り当てられている前置分周器がクリ アされます。 3.プ ログ ラム カウンタ( PC) を変更したり、条件付き試験の結果が真になると、命令実行は2サイクル掛かり、2番目のサイクルは NOPとして実行されます。 HERO and heavy friends 39 HERO and heavy friends © HERO 2006. 本書は中位PI C( 16F84) 留意点の記録です。 青字の部分はリ ンクとなっています。一般的に赤字の0, 1は論理0, 1を表します。その他の赤字は重要な部分を表します。
© Copyright 2024 Paperzz