エキゾチックな組み込み環境やマイクロコントローラー環境など、さまざまなプラットフォームで実行される小さなバイトコード VM を構築しています。
VM の各オペコードは可変長 (4 バイト以下、1 バイト以下) にすることができます。オペコードを解釈する際に、現在のオペコードの小さな「キャッシュ」を作成したいと考えています。ただし、多くの異なるプラットフォームで使用されているため、それを行うのは困難です。
したがって、期待される動作の例をいくつか示します。
- 8 ビット メモリ バスを備えた 8 ビット マイクロコントローラでは、複数の (遅い) メモリ操作をロードする必要があるため、1 バイトのみをロードする必要があります。現在のオペコードを実行する
- 8086 (16 ビット) では、1 バイトだけをロードすると、基本的に有用なデータを後で読み取れるように捨てることになるため、2 バイトをロードしたいと思いますが、2 バイトを超えてロードしたくないので、複数の操作が必要です
- 32 ビット ARM プロセッサでは、4 バイトをロードする必要があります。そうしないと、再度読み取る必要があるデータをスローするか、複数の操作を実行することになります。
これでいいと思っていれば簡単に扱えると思いますunsigned int
が、8ビットのAVRマイコンではintは16ビットで定義されていますが、メモリのデータバス幅は8ビットしかないので、メモリのロード操作は2回で済みます。必要。
とにかく、現在のアイデア:
usinguint_fast16_t
はほとんどのプラットフォームで期待どおりに動作するようです (ARM では 32 ビット、8086 では 16 ビット、x86-64 では 64 ビット)。ただし、AVR やその他の 8 ビット マイクロコントローラーは明らかに除外されています。
uint_fast8_t
usingはうまくいくかもしれないと思っていましたが、ほとんどのプラットフォームでは であると定義されているように見えますがunsigned char
、これは間違いなく最適ではありません
また、解決しなければならない問題がもう 1 つあります。それは、アラインされていないメモリ アクセスです。x86 では、これはおそらく問題にならないでしょう (理論的には 2 つのメモリ操作を行いますが、おそらくハードウェアにキャッシュされます)。ただし、ARM では、アライメントされていない 32 ビット アクセスを実行すると、3 倍のコストがかかる可能性があることがわかっています。 1 つのアラインされた 32 ビット ロードに相当します。アドレスがアラインされていない場合、アラインされたオプションをロードしてできるだけ多くのデータを取得したいのですが、別のメモリ操作は絶対に避けてください。
魔法のプリプロセッサ インクルードなどを使用して何らかの方法でこれを行う方法はありますか?それとも、プラットフォーム用にコンパイルする前に最適なキャッシュ サイズを手動で定義する必要があるだけですか?