アプリケーションノート 3960

MAXQ®の秘密の解明

筆者: Ben Smith

要約: MAXQコアは高性能のシングルサイクル、転送トリガアーキテクチャのCPUです。このアプリケーションノートでは、全体の命令セットが単純なMOVE命令を中心にどのように構築されているかを示すことによって、その能力を実証します。

MAXQプロセッサファミリは、1クロックサイクルで複数の処理を実行する高性能の8ビット、16ビット、および32ビットのシングルサイクルマイクロコントローラです。このアプリケーションノートではMAXQ20コアの内部機能を考察し、その優れた能力を紹介します。

プログラマのモデル

MAXQ20コアは16ビットCPUであり、これは全アキュムレータと大部分のワーキングレジスタ(スタック、データポインタ、カウンタ)が16ビット長であることを意味します。MAXQ20は、64kワードのコード空間(すなわち64kBの命令)と64kワード(128kB)のデータ空間をアドレス指定することができます(図1)。

なお、MAXQ20コアに基づくプロセッサの場合は、このメモリ空間の大部分は空き空間です。また、ユーティリティROMとデータRAMは上位32kBのコード空間に存在するため、この領域のユーザコードにアクセスするには、このアプリケーションノートの対象外であるコアの特別機能が必要です。

Figure 1. The programmer's model for the MAXQ20 core consists of 16 general-purpose accumulators, two loop counters, and a set of data pointers.
図1. MAXQ20コア用のプログラマモデルは、16個の汎用アキュムレータ、2個のループカウンタ、および1組のデータポインタから構成されています。

アキュムレータ

「アキュムレータ」と呼ばれる16個のレジスタが、汎用レジスタアレイを構成しています。アキュムレータポインタ(Accumulator Pointer)レジスタ(AP)が示すレジスタは、算術演算および論理演算の対象である「アクティブアキュムレータ」として指定されます。このため、APレジスタの値を変更すると、16個のアキュムレータの任意のアキュムレータを算術論理ユニット(ALU)演算の対象として指定することができます。アキュムレータポインタ制御(Accumulator Pointer Control)レジスタ(APC)を通じて、アクティブアキュムレータにアクセスするごとに、APを自動的にインクリメントまたはデクリメントするため、高精度の演算が容易になります。図2ではA[0]がアクティブアキュムレータですが、アキュムレータへのアクセスによって、APCレジスタの値に応じてA[1]またはA[15]がアクティブアキュムレータになることができます。

Figure 2. The active accumulator is designated by the AP register, which itself can be modified by accumulator access instructions.
図2. アクティブアキュムレータはAPレジスタによって指定されます。このAPレジスタ自体をアキュムレータアクセス命令によって変更することができます。

GRレジスタ

汎用レジスタ(General Register) (GR)は、16ビットワードからの各バイトの抽出に便利です。プログラマはこのGRを使って、バイトをワードに組み立てることができます。すなわち、下位バイトをGRL (汎用レジスタの下位バイト(General Register-Low byte))に、上位バイトをGRH (汎用レジスタの上位バイト(General Register-High byte))にロードし、組み立てられたワードをGRで読み取ります。また、プログラマはGRレジスタを使って、ワードをその各構成バイトに分解することができます。GRにロードされたワードをGRS (汎用レジスタのスワップ(General Register-Swapped))を用いてバイトスワップ形式で読み取ることができます。最後に、GRXL (汎用レジスタの拡張下位バイト(General Register eXtend Low byte))を読み取って、GRLレジスタにロードされたバイトを符号拡張してワードにすることができます。図3を参照してください。

Figure 3. The GR register supports byte extraction, byte-swapping, and 16-bit sign extension.
図3. GRレジスタは、バイト抽出、バイトスワップ、および16ビット符号拡張をサポートしています。

ループカウンタ

ループカウンタ0 (LC[0])とループカウンタ1 (LC[1])の2個のループカウンタがあります。これらのレジスタを汎用レジスタとして使用可能ですが、カウンタが非ゼロ(DJNZ)命令である場合は、デクリメントおよびジャンプ用のループカウンタになります。

スタック

MAXQ20コアは、専用の16レベルスタックを内蔵しています。スタックポインタは使用される次のスタック位置か、またはPUSH命令またはCALL命令を示します。

データメモリポインタ

MAXQマイクロコントローラは、データメモリにアクセスするための3個のポインタを備えています。DP[0]およびDP[1]の2個のポインタは、単純な16ビットポインタです。第3のポインタは、ベースアドレスポインタを(BP)を8ビット無符号オフセット(OFFS)に追加すると生成されます。

なお、3個のデータポインタのいずれか1つでアドレス指定されるデータメモリは、命令ポインタでアドレス指定されるコードメモリとは異なります。MAXQのプロセッサはすべてメモリ管理ユニット(MMU)を内蔵しているため、いずれのメモリセグメントもコードやデータとして扱うことが可能であり、またコードバスとデータバスは分離独立しています。コードおよびデータのフェッチ命令用のバスがこのように分離しているのはMAXQ20技術の基盤となる要素であり、シングルクロックサイクルでコードとデータの同時アクセスが可能になります。

転送トリガアーキテクチャ

プログラマモデルを調べると、命令をロードし、命令をデコードして、CPUの特定要素を作動させる従来型の命令フェッチ-デコードユニットが存在すると結論付ける人がいるかもしれません。しかし、その結論は誤っています。MAXQアーキテクチャがその他の従来型CPUと異なっているのは、MAXQコアの転送トリガ特性です。

転送トリガは、単純なMOVE (転送)命令によってCPUで利用可能なあらゆる関数を実行させる手法です。MAXQのアセンブラは30を超える命令コードをサポートし、以下のようなMAXQ命令セットでいずれの命令でもエンコードすることができます。
        move Ma[b], Mc[d]
または
        move Ma[b], #immediate_value
ここで、記号表示Ma[b]はレジスタモジュールaとレジスタサブデコードbを示します。簡単に言うと、ADD、ビット操作、外部メモリの参照などのいずれの命令も、2個のレジスタ間の転送として、またはレジスタへの即値の転送としてコーディングされます。

MAXQの命令が実行されると、デスティネーションレジスタにソースレジスタの内容または即値がロードされます。また、このデータ転送によって、ポインタのインクリメントやデクリメント、あるステータスビットの設定、またはその他のある関数などの他のイベントをトリガすることができます。したがって、このアーキテクチャは転送トリガアーキテクチャです。このアーキテクチャをサポートするには、大きなレジスタの補足が必要です。MAXQ20コアには、ペリフェラルレジスタ空間とシステムレジスタ空間の2つに大別される合計512のレジスタアドレスがあります(図4)。

最初の6つのレジスタモジュール(モジュール0~5)はペリフェラルレジスタ専用で、最後の9つのモジュール(モジュール7~F)はシステムレジスタとして割り当てられています(モジュール6は予備)。ペリフェラルレジスタモジュールがMAXQプロセッサのあるタイプから別のタイプに変更されても、システムレジスタはいずれのMAXQプロセッサでも同じ状態を維持します(図5)。

Figure 4. Register assignments in the MAXQ20 core are split into two regions: register banks 0 to 5 are peripheral registers and can change from one MAXQ part to another; banks 7 to 15 are system registers and remain relatively fixed on all MAXQ parts.
図4. MAXQ20コアのレジスタ割当は、以下のように2つの領域に分割されます。すなわち、レジスタバンク0~5はペリフェラルレジスタで、あるMAXQデバイスと 別のMAXQデバイスでは変更可能です。バンク7~15はシステムレジスタで、いずれのMAXQデバイスにおいても比較的固定されています。

Figure 5. The MAXQ system register map consists of the registers present in all MAXQ20-based processors and additional decodes to implement the instruction set.
図5. MAXQシステムレジスタマップは、MAXQ20ベースのすべてのプロセッサ内にあるレジスタと、命令セットを実装する追加デコードから構成されます。

MAXQの命令のデコード

いずれのMAXQ命令も実際にはMOVE (転送)であるため、いずれの命令も以下の3つの領域に分類することができます。すなわち、データの転送元を指定するSOURCE (ソース)領域、データの転送先を指定するDESTINATION (デスティネーション)領域、およびソースが即値(FORMAT == 0)か、またはレジスタ指定子(FORMAT == 1)であるかを指定するフォーマットビットです(図6)。

Figure 6. A MAXQ instruction consists of three parts: a source designator, a destination designator, and a source format bit to determine if the source is an immediate operand or a register operand.
図6. MAXQ命令は、ソース指定子、デスティネーション指定子、およびソースが即値オペランドかまたはレジスタオペランドかを決定するソースフォーマットビットから構成されています。

命令コード0x0923を例にしましょう。この命令では、FORMATビットはクリア状態で、ソース指定子(23)を8ビットの即値として扱う必要があることを示しています。デスティネーションモジュールはモジュール9であるアキュムレータアレイです。このアレイ内のレジスタ0はアキュムレータA[0]です。このため、この命令によって、値0x0023がレジスタA[0]にロードされます。この場合、ソースまたはデスティネーション指定子に関連する副作用はありません。

もう1つの例として、0xBF09を検討しましょう。この命令では、FORMATビットが設定され、ソース指定子をレジスタと見なす必要があることを意味します。モジュール9のレジスタ0は、上述したようにアキュムレータA[0]です。デスティネーション側では、モジュールFはデータポインタモジュールであり、レジスタ3 (命令ではビット14:12)はデータポインタDP[0]を表します。このため、この命令は、A[0]の内容をDP[0]に転送します。

なお、場合によって、レジスタモジュール内の各場所は実際のレジスタを示す場合と、示さない場合があります。また、各場所が実際のレジスタを示すことができても、そのレジスタサブデコードにアクセスされるときに、副作用が発生することもあります。たとえば、前の例を0xAF09で少し変更してみましょう。デスティネーションサブデコードのみが変更されました。すると今度はレジスタDP[0]にロードする代わりに、命令はDP[0]をデクリメントしてから、DP[0]が指定する新しいメモリ位置への格納操作を開始します。すなわち、この命令はプリデクリメントされたポインタで間接格納を実行します。MAXQのアセンブラでは、これはmove @ DP[0], A[0]としてコーディングされますが、move M15[2], M9[0]と同様に容易にコーディングすることができます。

プレフィックスレジスタ

モジュール当り32個のレジスタがありますが、ソースレジスタの選択用は4ビットのみで、デスティネーションレジスタの指定用は3ビットのみです。一見すると、これは、レジスタサブデコードの半分を読み取りできず、レジスタサブデコードのまるまる4分の3も書き込むことができないことを意味します。幸いにも、MAXQアーキテクチャ設計はこれに対処しています。MAXQプロセッサはすべて、これらの追加レジスタアドレスビットを提供し、ワード幅のmove (転送)の上位バイトを提供するプレフィックスレジスタを備えています。詳細については、「モジュール11—プレフィックス」の項を参照してください。

一度に1モジュールのMAXQ命令セットの作成

以下の項では、システムレジスタモジュールと、これらのモジュールが連携して定義/未定義命令を作成する方法について詳述します。まず、MAXQ20コアの中核であるアキュムレータアレイを調べてみましょう。

モジュール9—アキュムレータ

MAXQアーキテクチャは、大部分のバリアントでは16個しか実装されていませんが、最大32個のアキュムレータをサポートします。これらのアキュムレータには、モジュール9を通じて直接アクセスされます。このモジュール内の各サブデコードは、1個のアキュムレータを表します。モジュール9は概念的には最も簡易なモジュールですが、アキュムレータアレイに影響を及ぼすモジュールがさらに2つあります。

モジュール8—システム制御

このモジュールは、割込み制御やプログラムステータスフラグなどのシステム処理の各状況を管理する多くのレジスタを備えています。これらのレジスタの多くはこのアプリケーションノートの範囲外であるため、詳細についてはデバイス仕様を参照してください。表1にはこれらのレジスタモジュールの一部が記載されています。

表1. モジュール8の機能
Sub ファンクション S/D 説明
0 アキュムレータポインタレジスタ S/D アクティブアキュムレータを指定します。すなわち、ALU操作のデスティネーションとして機能するアキュムレータです。
1 アキュムレータポインタ制御レジスタ S/D APに動作の指示をします。本論では8ビットの汎用レジスタです。
4 プログラムステータスフラグレジスタ S/D ユーザがメインプログラムで監視することを所望するフラグ(carry、zero、equal)を含みます。このレジスタは通常、ソースとして扱われますが、デスティネーションにもなります。この中の幾つかのビットは読取り専用であることに注意してください(例えば、Zフラグはアクティブアキュムレータのすべてのビットの論理NORです)。
5 割込み制御レジスタ S/D 割込みサブシステムの管理。
6 割込みマスクレジスタ S/D 通常はモジュールレベルの割込みをマスクするビットが含まれます。
7 コンパレータレジスタ DO 書込み専用のサブデコード。実際のメモリが存在しないため、実レジスタではありません。このサブデコードが書き込まれると、ソースオペランドが現在のアキュムレータの内容と一致すると、PSFにEqualビットが設定されます。一致しない場合にはEqualビットはクリアされます。
8 システム制御レジスタ S/D システムの操作の状況を制御するビットが含まれています(読出し/書込み)。
11 割込み識別レジスタ SO 割込みのソースを特定するビットの集合を含みます。
14 クロック制御レジスタ S/D システムクロックに関するビットを含みます。特に、マスタクロックの分周比、および個々のマイクロコントローラでソースが2個以上の場合のクロックソースを制御します。
15 ウォッチドッグ制御レジスタ S/D ウォッチドッグタイマの動作を制御します。ほとんどのMAXQマイクロコントローラはプログラムのループ状態で停止が継続した場合、プロセッサをリセットするウォッチドッグタイマを備えています。

APおよびAPCレジスタは、特に注目する価値があります。APレジスタはいずれのアキュムレータレジスタがアクティブアキュムレータであるかを決定します。すなわち、算術演算、論理演算、およびビット単位の演算の対象を指定します。APレジスタは、アレイ内のいずれのアキュムレータも指定することができます。

APCレジスタは、アキュムレータ処理後にAPレジスタの変更方法を設定するビットセットを備えています。このため、選択可能な2のべき乗の係数でカウントをロールオーバして、APレジスタをインクリメントまたはデクリメント可能であるため、高精度の演算が容易になります。

モジュール10—アキュムレータ機能

モジュール10において、アキュムレータの実際の作業の大部分が実行されます。モジュール10によって、従来型のALU機能にアクセスし、アクティブアキュムレータにビットレベルでアクセスすることができます。モジュール10はユニークであり、ソース、デスティネーション、またはソースおよびデスティネーションとして機能しているかに応じて、さまざまに動作します(表2)。

表2. ソースとしてのモジュール10
Sub ファンクション 説明
0 アクティブアキュムレータ アクティブアキュムレータの内容はデスティネーションへ転送され、APはAPCに従って変化します。
1 アクティブアキュムレータ アクティブアキュムレータの内容はデスティネーションへ転送され、APは変化しません。

ソースがモジュール10で、デスティネーションがモジュール10以外のモジュールの場合は、アキュムレータの内容はデスティネーションに転送されます。サブコードがゼロの場合は、APレジスタはAPCレジスタのビットに応じて変更されます。サブデコードが1の場合は、APレジスタは変更されません。

なお、マクロアセンブラの現行バージョンはサブデコード1をサポートしていません。これは、サブデコード1を指定するニーモニックまたは指定子がないためです。このため、命令move A[1], ACCによって、命令コード0x990Aが必ず生成され、0x991Aは生成されません(表3)。

表3. デスティネーションとしてのモジュール10
Sub ファンクション 説明
0 MOVE ソースはアキュムレータに転送されます。
1 AND ソースの内容はアキュムレータと論理ANDがとられます。
2 OR ソースの内容はアキュムレータと論理ORがとられます。
3 XOR ソースの内容はアキュムレータと排他論理ORがとられます。
4 ADD ソースの内容はアキュムレータに算術的に加算されます。MSBからのオーバフローによってキャリービットがセットされます。
5 SUB ソースの内容はアキュムレータから算術的に減算されます。アンダーフローによってキャリービットがセットされます。
6 ADDC ソースの内容とキャリービットがアキュムレータに加算されます。
7 SUBB ソースの内容とキャリービットがアキュムレータから減算されます。

モジュール10がデスティネーションとして指定され、ソースが即値またはモジュール10以外のモジュールの場合は、ソースはALUを通じて送出されます。デスティネーションはソースから直接供給されず、ALUの出力から供給されます。このようにして、算術命令と論理命令が実装されます。

なお、ソースレジスタとして機能することに対しては制限がありません。即値、間接メモリ位置、またはスタックの値やペリフェラルレジスタにもなることができます(表4)。

表4. ソースおよびデスティネーションとしてのモジュール10
Dest Sub SRC Sub ファンクション 説明
0 0 MOVE アキュムレータの内容が同じアキュムレータへ移動します。論理的にはNOPです。しかし、APレジスタは変化することができます。
1 CPL アキュムレータのビットごとに補数が取られます。
2 SLA アキュムレータは1ビットだけ左シフトします。低位ビットはゼロに設定されます。高位ビットはコピーされてキャリーになります。
3 SLA2 アキュムレータは2ビットだけ左シフトします。低位の2ビットはゼロに設定されます。ビット14はコピーされてキャリーになります。
4 RL アキュムレータは1ビットだけ左に回転します。ビット15はビット0にコピーされ、ビット15はキャリーにもコピーされます。
5 RLC アキュムレータは1ビットだけ左に回転します。ビット15はキャリーにコピーされ、キャリーはビット0にコピーされます。
6 SLA4 アキュムレータは4ビットだけ左シフトします。低位の4ビットはゼロに設定されます。ビット12がキャリーにコピーされます。
7 XCHN アキュムレータの各バイトがニブル単位で反転します。例として0x1234は0x2143になります。
8 XCH アキュムレータのバイトが反転します。例として0x1234は0x3412になります。
9 NEG アキュムレータは算術的にネゲートされます。
10 SR アキュムレータは1ビットだけ、右にシフトします。ビット15にはゼロがロードされます。ビット0はキャリーに転送されます。
11 SRA4 アキュムレータは4ビットだけ、右にシフトします。高位の4ビットにはゼロが設定されます。ビット3はキャリーにコピーされます。
12 RR アキュムレータは右に1ビットだけ回転し、ビット0はビット15にコピーされ、ビット0はキャリーにコピーされます。
13 RRC アキュムレータは右に1ビットだけ回転し、ビット0はキャリーにコピーされ、キャリーはビット15にコピーされます。
14 SRA2 アキュムレータは右に2ビットシフトし、高位の2ビットはゼロに設定され、ビット1はキャリーにコピーされます。
15 SRA アキュムレータは右に1ビットシフトし、高位ビットはゼロに設定され、低位ビットはキャリーにコピーされます。
1 Bit AND C キャリービットがアキュムレータの指定ビットと論理ANDされます。
2 Bit OR C キャリービットがアキュムレータの指定ビットと論理ORされます。
3 Bit XOR C キャリービットがアキュムレータの指定ビットと排他論理ORされます。
5 0 C 0 キャリービットがゼロに設定されます。
1 C 1 キャリービットが1に設定されます。
2 C C キャリービットの補数がとられます。
3 NOP 保証されたNOP
6 Bit C ACC アキュムレータの指定ビットがキャリーにロードされます。
7 Bit ACC C キャリーはアキュムレータの指定ビットにロードされます。

ソースおよびデスティネーション指定子がモジュール10の場合は、アキュムレータ専用命令か、またはキャリービットを含むビット操作です。いずれの場合でも、ソースとデスティネーションサブデコードを使って、命令を指定することができます。

デスティネーションサブデコード0は、補数、否定、全シフト、ローテート、および交換命令などのアキュムレータ専用命令のホームです。デスティネーションサブデコード1、2、3、6、および7は、キャリービットを使用する命令とビット単位のロードで構成されます。最後に、デスティネーションサブデコード5は、ロード0および1と補数というキャリー専用命令を備えています。

デスティネーションサブデコード5の1つのソースサブデコードは、指定NOP命令であることに注意してください。副作用を持たず同時に空きレジスタ位置をアドレス指定する動作はいずれもNOPとして機能し、MOVE M10[5]、M10[3]は、現行または今後のMAXQデバイスでは動作しないことが明確に保証されています。これは、NOPニーモニック用のすべての現行アセンブラで生成されているオペコード(0xDA3A)です。

モジュール12—命令ポインタ

モジュール12は、多数の条件付きロード命令を備えているためユニークです。モジュール12がソースモジュールとして使用される場合は、IPがデスティネーション指定子にコピーされるだけです。ただし、モジュール12がデスティネーションである場合は、指定条件を満たさなければ、命令は実行されません(表5)。

表5. モジュール12のサブデコード
Sub 説明
0 ソースの場合はIPからデスティネーションをロードします。デスティネーションの場合はソースからIPをロードします。
1 ソースの場合はIPからデスティネーションをロードします。デスティネーションの場合は、ACC == 0の場合にのみ、ソースからIPをロードします。
2 ソースの場合はIPからデスティネーションをロードします。デスティネーションの場合は、C == 1の場合にのみ、ソースからIPをロードします。
3 ソースの場合はIPからデスティネーションをロードします。デスティネーションの場合は、直近のCMP命令でEQフラグがセットされた場合にのみ、ソースからIPをロードします。
4 ソースの場合はIPからデスティネーションをロードします。デスティネーションの場合は、アキュムレータの高位ビットがセットされた場合にのみ、ソースからIPをロードします。
5 ソースの場合はIPからデスティネーションをロードします。デスティネーションの場合は、ACC == 0の場合にのみ、ソースからIPをロードします。
6 ソースの場合はIPからデスティネーションをロードします。デスティネーションの場合は、C == 0の場合にのみ、ソースからIPをロードします。
7 ソースの場合はIPからデスティネーションをロードします。デスティネーションの場合は、直近のCMP命令でEQフラグをクリアした場合にのみ、ソースからIPをロードします。

また、モジュール12は8ビット即値ソースからロードされるためユニークであり、ソース値は符号付き整数と見なされ、命令ポインタの直前のプリインクリメントされた内容に追加されます。この追加によって相対短分岐が容易になるため、コードサイズが大幅に節減されます。また、いずれの短分岐命令または長分岐命令も条件付きにすることができることを意味します。

このモジュールは、命令ポインタ(Instruction Pointer)レジスタ(IP)の簡易なロードと格納のみをサポートしています。CALL命令は、スタックにプッシュするIP命令ではなく、IPのロードも行うスタック命令と見なされます。このため、CALL命令の転送はスタックポインタモジュール(モジュール13)における転送です。また、明示的なRET命令がなく、これはPOP IPとしての働きをします。

モジュール13—スタックポインタ

モジュール13はスタックポインタ関連のレジスタだけでなく、ループカウンタおよび割込みベクトルも備えています。なお、サブデコードのうちいくつかはデスティネーションとしてのみ有効で、1つ(サブデコード8)はソースとしてのみ有効です(表6)。

表6. モジュール13のサブデコード
Sub ファンクション S/D 説明
0 PUSH/POP S/D デスティネーションの場合は、スタックポインタをインクリメントし、ソースオペランドをスタックに格納します。ソースの場合は、スタックの値をデスティネーションにロードしてスタックポインタをデクリメントします。
1 スタックポインタ S/D 内部の専用スタックの直近に使用した位置を示します。
2 割込みベクトル S/D 割込みサービスルーチンが存在するプログラムメモリの位置を示します。
3 CALL DO 現在のIPをスタックに退避して、その後、IPをソースオペランドからロードします。ソースオペランドとして使用すると、予測できない結果になります。
4 DJNZ LC[0] DO LC[0]をデクリメントし、LC[0] != 0の場合は、IPにソースをロードします。ソースオペランドとして使用すると、予測できない結果になります。
5 DJNZ LC[1] DO LC[1]をデクリメントし、LC[1] != 0の場合は、IPにソースをロードします。ソースオペランドとして使用すると、予測できない結果になります。
6 LC[0] S/D データはループカウンタ0へ/から転送されます。
7 LC[1] S/D データはループカウンタ1へ/から転送されます。
8 POPI SO スタックの値がデスティネーションにコピーされ、スタックポイントはデクリメントされ、IN SERVICEビットはクリアされます。これは主としてRETI操作を実装するために使われます。

サブデコード3、4、および5は、IPレジスタのプロキシとして機能します。サブデコード3は、インクリメントされた命令ポインタがスタックにプッシュされると、命令ポインタをロードするため、従来型のCALL命令が実装されます。サブデコード4および5は指定したループカウンタのプリデクリメントされたバージョンをループカウンタにロードし、プリデクリメントされたループカウンタが非ゼロの場合は命令ポインタにソースオペランドをロードします。このデスティネーションサブコードにロードするソースはいずれでも可能です。命令DJNZ LC[0], A[1]は完全に有効です。この場合は、この命令はLC[0]をデクリメントし、デクリメント演算の結果が非ゼロの場合はA[1]のアドレスに分岐します。

モジュール14—GR、BP、およびDPC

モジュール14はDPCレジスタ、GRレジスタ、およびベースポインタやオフセットレジスタに関連する全レジスタを備えています(表7)。

表7. モジュール14のサブデコード
Sub ファンクション S/D 説明
0 @BP[offs] S/D BP+offsで指定されるデータメモリ位置に書込みまたは読出しを行います。
1 @BP[offs++] S/D ソースの場合、BP+offsで指定されるデータメモリ位置の読出しを行い、offsをインクリメントします。デスティネーションの場合は、offsをインクリメントしてソースデータをBP+offsにストアします。
2 @BP[offs--] S/D ソースの場合、BP+offsで指定されるデータメモリ位置の読出しを行い、offsをデクリメントします。デスティネーションの場合は、offsをデクリメントしてソースデータをBP+offsにストアします。
3 offs S/D 8ビットのオフセットレジスタです。
4 DPC S/D データポインタ制御レジスタがいずれのデータポインタが現在のソースポインタであるか、および各データポインタのワード/バイトステータスを決定します。
5 GR S/D 16ビットの汎用レジスタ
6 GRL S/D 16ビット汎用レジスタの下位バイト
7 BP S/D 16ビットのベースメモリポインタ
8 GRS SO GRのバイトスワップしたバージョン
9 GRH S/D 16ビット汎用レジスタの高位バイト
10 GRXL SO GRの符号拡張の下位バイト
11 BP[offs] SO ベースポインタとオフセットの和

データポインタ制御(Data Pointer Control)レジスタ(DPC)は、データポインタの動作方法を示します。特に、データポインタがワードモードまたはバイトモードで動作しているかどうかを定義する1ビットがデータポインタごとに含まれます。また、このレジスタは、いずれのポインタが現在のソースポインタであるかを定義するフィールドも備えています。ソースポインタのロード時にソースがアクセスされ、オペランドデータ用のバスは1つしかないため、このフィールドが必要です。

16ビットデータ用にバイトアクセスが必要な場合に、GRレジスタは便利です。GRに16ビットデータがロードされると、低位および高位バイトをそれぞれGRLおよびGRHレジスタを通じて検索することができます。GRSレジスタはGRのバイトスワップバージョンを備え、また上位バイトは低位バイトの符号拡張である点を除いてGRXLレジスタはGRLレジスタと同じです。

ベースポインタ(Base Pointer)レジスタ(BP)は、MAXQアーキテクチャ内の3個のデータメモリポインタレジスタの1つであり、オフセットレジスタをサポートする唯一のレジスタです。BPは通常、データ構造の基本を指定し、8ビット無符号オフセットレジスタは構造内のデータエレメントを指定します。なお、このレジスタのインクリメント/デクリメントバージョンはオフセットレジスタのみを変更し、ベースレジスタを変更しません。

モジュール15—データポインタ

モジュール15は、MAXQアーキテクチャの3個のデータポインタのうちの2個を備えています。サブデコードに応じて、このモジュールへのアクセスによって、直接または間接ロードや格納が実行され、場合によっては間接アクセスの後にデータポインタがインクリメントまたはデクリメントされます。これらのレジスタサブデコードをソースまたはデスティネーションレジスタとして使用することができます(表8)。

表8. モジュール15のサブデコード
Sub ファンクション 説明
0 @DP[0] DP[0]で指定されるデータメモリ位置に書込みまたは読出しを行います。
1 @DP[0]++ ソースの場合、DP[0]で指定されるデータメモリ位置の読出しを行い、DP[0]をインクリメントします。デスティネーションの場合は、DP[0]をインクリメントしてソースデータをDP[0]にストアします。
2 @DP[0]-- ソースの場合、DP[0]で指定されるデータメモリ位置の読出しを行い、DP[0]をデクリメントします。デスティネーションの場合は、DP[0]をデクリメントしてソースデータをDP[0]にストアします。
3 DP[0] データポインタ0
4 @DP[1] DP[1]で指定されるデータメモリ位置に書込みまたは読出しを行います
5 @DP[1]++ ソースの場合、DP[1]で指定されるデータメモリ位置の読出しを行い、DP[1]をインクリメントします。デスティネーションの場合は、DP[1]をインクリメントしてソースデータをDP[1]にストアします。
6 @DP[1]-- ソースの場合、DP[1]で指定されるデータメモリ位置の読出しを行い、DP[1]をデクリメントします。デスティネーションの場合は、DP[1]をデクリメントしてソースデータをDP[1]にストアします。
7 DP[1] データポインタ1

モジュール7—ブール変数操作

ブール変数操作(BVM)モジュール(モジュール7)によって、標準的なMAXQプロセッサにおいて多数のレジスタのビット抽出とビット設定/クリアが可能です(図7)。なお、すべてのモジュールがBVMマシンと接続されているわけではありません。通常は、ペリフェラルモジュールのみがBVMと接続され、システムレジスタは未接続です。このため、BVMとシステムレジスタ間のデータの転送は、おそらく予測不可能な結果をもたらします。

Figure 7. Subdecodes of module 7 designate the bit to extract or replace and, if a source designator, the immediate bit value.
図7. モジュール7のサブデコードは、ソース指定子、即ビット値の場合、抽出または置換するビットを指定します。

デスティネーション指定子としてBVMはキャリービットのプロキシとして機能します。ソースの1ビットが抽出され、キャリービットにコピーされます。BVMがソース指定子の場合は、サブデコードのビット3 (完全ソース指定子のビット7)に与えられた値がデスティネーションの指定ビットにコピーされます。

なお、BVMは、ペリフェラルレジスタのビット0~7でのみ動作します。これには大部分のペリフェラルレジスタが対応可能です。多くのレジスタ(特にI/Oポート)はわずか8ビット長であるためです。ただし、16ビットペリフェラルレジスタにアクセスする場合は、下位8ビットのみを利用可能です。

モジュール11—プレフィックス

プレフィックスモジュールは、あらゆる16ビットマイクロコントローラの制限に対処するMAXQアーキテクチャの独自機能です。16ビットレジスタの場合、即値ロード命令には16ビットオペランドが必要です。これは、有効な即値ロード命令には16ビット以上が必要であることを意味します。

下位および上位バイトへの個別のアクセスを可能にするレジスタや可変長命令など、この制限のソリューションが複数あります(MAXQ GRレジスタはこの一例です)。各ソリューションはデコードロジックを複雑化したり、または新しいレジスタを必要とするため、いずれのソリューションも理想的ではありません(図8)。

Figure 8. When the prefix register is a destination, the 8-bit immediate source provides the high-order byte for 16-bit immediate operands; the destination subdecode provides additional bits to permit addressing of all 32 registers in each module for both source and destination operands.
図8. プレフィックスレジスタがデスティネーションの場合、8ビット即値ソースは16ビット即値オペランド用に高位バイトを提供し、デスティネーションサブデコードはソースおよびデスティネーションオペランド用にモジュールごとに32個の全レジスタのアドレス指定を可能にする追加ビットを提供します。

プレフィックスメカニズムを通じて、2通りの方式でこのプロセスが向上します。第1に、追加ビットが特に必要な命令のみをプレフィックスすると、このメカニズムはコード空間と実行時間を節減します。第2に、即値オペランド用のほかに、レジスタ指定子用の追加ビットを備えると、このメカニズムはレジスタ空間のサイズを拡張しながら、アーキテクチャ全体を保持します。

レジスタモジュール当り32個のレジスタがありますが、4ビットのみでソースレジスタを指定し、3ビットのみでデスティネーションレジスタを指定していることに留意してください。プレフィックスメカニズムを通じて、これらの追加ビットが提供されます。

プレフィックスメカニズムは、いくつかの点でユニークです。第1に、命令のデスティネーション部の特定ビットを即値ソースビットとして使用して、ソースアドレス用に15を上回るレジスタサブデコードと、デスティネーションアドレス用に7を上回るレジスタサブデコードにアクセスすることができます。このように、単一のプレフィックス命令によって、任意のレジスタまたは即値から任意のレジスタサブデコードにアクセスすることができます。

第2に、プレフィックスレジスタにロードされる値は1クロックサイクルの間しか存続しないため、プレフィックスレジスタはユニークです。その後に、レジスタはゼロに自動的にクリアされます。すなわち、プレフィックスレジスタへの転送は、プレフィックスレジスタで変更される命令の直前の命令である必要があります。また、プレフィックス命令は割込み不可能であることも意味します。割込みがプレフィックス処理に続いて発生した場合は、割込みがメイン関数に戻るとプレフィックス情報は消失します。

図9に示すように、プレフィックスレジスタのビットはソース指定子、デスティネーション指定子、および即値に移動します。 このため、ほとんどの命令はシングルサイクルで実行されますが、以下の命令には2サイクルが必要です。すなわち、7を上回るデスティネーションレジスタサブデコードに対処する命令、15を上回るソースレジスタサブデコードに対処する命令、または255を上回る即値をロードする命令です。

Figure 9. The prefix register provides the additional bits needed for 16-bit immediate operands and to address all 32 registers in each module as both source and destination.
図9. プレフィックスレジスタは、16ビット即値オペランドに必要な、各モジュールの32個の全レジスタをソースおよびデスティネーションとしてアドレス指定する追加ビットを備えています。

このプロセスを示すには、命令move A[0], #010hを考察してください。これは即値をモジュール9のレジスタ0に転送し、アセンブラは0910という命令コードを生成します。ただし、命令がmove A[10], #0320hである場合は、アセンブラはプレフィックス命令2B03 2920を自動的に挿入する必要があります。

プレフィックス命令がない場合は、命令コード2920は、move A[2], #020hに変換されます。ただし、プレフィックスによって、1ビットがデスティネーション指定子に、追加ビットが即値に追加され、プロセッサが2サイクルを上回るサイクルを必要とせずに、任意の値を任意のレジスタサブデコードにロードすることができます。

幾つかの例

独特なMAXQ20コアの方式のため、命令の幾つかは他のプロセッサでは単純には使用可能でないものが使用可能です。

ベクトル割込み

MAXQ20コアは1個の割込みベクトルレジスタしか備えていません。これはある種の制限であると思われるかもしれません。しかし、デバイスAがポート0のビット0に接続され、デバイスBがポート0のビット1に接続されている、2つの外部割込みを備えるシステムを考えてみましょう。この場合、割込みの選択はjump PIOのように簡単になります。そして、アドレス0ではコードは次のようになります。
        0000: IRET
        0001: jump SERVICE_DEVICE_A
        0002: jump SERVICE_DEVICE_B
        0003: jump SERVICE_DEVICE_A
この例では、デバイスAが割込み処理において優先順位が高くなっています。すなわち、両方の割込み要求のラインがアクティブ(ポート0がビット0と1をアクティブにする)になった場合、デバイスAが処理されます。割込み処理のサービスルーチンの最後には、デバイスAはすでにアクティブではなく、デバイスBが処理されると考えられます。

タスクマネジャー

多くのアプリケーションにおいて、マルチタスク環境の原型を作り出すためにタスクのリストを繰り返して探索することが望ましいと言えます。これはプリエンプションが要求されない(またはリアルタイムの理由で望ましくない)場合に有用です。MAXQの方式がこの種の手順を単純にしています。
task_wheel_init:
        move dp[0], #task_list
task_wheel:
        move dp[0], dp[0]
        jump @dp[0]++
.
.
.
task_list:
        dw      task_01
        dw      task_02
        dw      task_03
        dw      task_wheel_init
この例では、DP[0]がタスクのリストを指定します。このtask_wheelルーチンでは、DP[0]がソースポインタとして選択され、命令ポインタにはタスクのリストからロードされます。各タスクが終わると、RETを実行する代わりに、単にtask_wheelルーチンにジャンプします。

表の中の最後のエントリではポインタの再初期化を実行するように仕向けられます。そしてtask wheelが再び、表のスキャンを開始します。

リストの探索

多くの場合、タグ付きのエントリがないかを探すために大きさが均一でないオブジェクトリストを高速で探索することは有用です。これは幾つかのプロセッサ方式では困難です。その理由はメモリをアクセスする機能がALUから削除されているからです。MAXQではこれは簡単なタスクとなっています。

TAG LEN データ
3F 09 00 01 02 03 04 05 06 07 08          
17 0E 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D
35 07 20 21 21 22 23 24 25              

この例では、リストはタグ、長さ、およびデータストリングから構成されるデータオブジェクトを持つと仮定しています。このリストを探索するルーチンを次に示します。
item_seek:
        move acc, @dp[0]++     ;Get tag
        jump z, item_not_found ;Tag==0 means end of list
        cmp  a[1]              ;A[1] has target tag
        jump e, item_found     ;If item==target, exit
        move acc, @dp[0]++     ;If no match, get data len
        add  dp[0]             ;Add to pointer
        move dp[0], acc        ;Store pointer back
        jump item_seek         ;...and seek next item.
8個の命令によって、このルーチンはリストを探索し、一致またはリストを終結させるゼロエントリを探索します。8MHzのMAXQコアでは、このルーチンは1秒に百万回のエントリを探索します。

まとめ

たとえMAXQコアが小型で一見単純でも、転送トリガアーキテクチャによって速度と柔軟性は抜群です。ペリフェラルはレジスタインタフェースを通じて直接アドレス指定されるため、組込みペリフェラルを通じたデータ転送の速度は驚異的になります。結局、いずれのMAXQコアも、広範囲のマイクロコントローラアプリケーションに最適です。