A.1.1 短い命令長でアクセスできる領域へ配置する

CC-RLでは変数や定数にfar属性,near属性,またはsaddr属性のいずれかの属性を指定した上で,各々を各属性と同じ名前を持つ領域,すなわち,far領域,near領域,またはsaddr領域に配置します。

変数や定数をアクセスする命令のサイズはこの順番で小さくなるため,変数や定数をnear属性(またはsaddr属性)にしてnear領域(またはsaddr領域)に配置するとコードサイズが小さくなります。

一方,領域のサイズもこの順番で小さくなるため,変数や定数の合計サイズが大きい場合には各変数をどの領域に配置するかの優先順位を付ける必要があります。

 

以下では,各属性の指定方法,各領域とその配置方法及びについて詳しく説明します。

(1)

変数や定数に属性に指定する方法

変数や定数にはオプションやキーワードを使って,属性を指定します。

指定方法は以下の4つで,優先度はこの順番で高くなります。

詳細は各オプションやキーワード,および,「2.6.6 near,farとの関係」を参照してください。

(a)

-cpuオプション

ただし,変数や定数のデフォルト属性は常にnear属性

(b)

-memory_modelオプション

ただし,変数や定数のデフォルト属性は常にnear属性

(c)

-far_romオプション

ROMデータはデフォルトでfar属性になる

(d)

__near/__far/_saddr キーワード

変数は各キーワードで指定された属性になる

例 1.

-far_romオプション非指定時

long                x;      //near属性
long __near         y;      //near属性
long __far          z;      //far属性
const int           c;      //near属性
const int __near    d;      //near属性
const int __far     e;      //far属性
char __saddr        s;      //saddr属性

例 2.

-far_romオプション指定時

long                x;      //near属性
long __near         y;      //near属性
long __far          z;      //far属性
const int           c;      //far属性
const int __near    d;      //near属性
const int __far     e;      //far属性
char __saddr        s;      //saddr属性

(2)

変数や定数を各領域に配置する優先度

一般的には,変数の静的参照回数が多い変数を,命令サイズが小さな領域に割り付けるとプログラム全体のコードサイズが小さくなります。

しかし,命令サイズが小さな領域はその領域サイズも小さいため,効率的に使う必要があります。

そこで,領域1バイトあたりの削減効率を最大化することを考えると,変数の静的参照回数を変数サイズで割った値が大きい変数ほど命令サイズが小さな領域に割り付けると良いとわかります。

そこで,優先度は以下と考えられます。

優先度 = 変数の静的参照回数 / 変数サイズ

 

ここで,変数の静的参照回数は,オブジェクト・コード上の参照回数を指し,Cソース上の参照回数とは異なります。

RL78では変数参照に使える命令は1バイトや2バイトのアクセス幅のみのため,例えば4バイト変数を参照するには2つの命令が必要になります。

したがって,Cソース上で4バイト変数を1回参照すると,オプジェクト・コード上では2回参照することになります。

オブジェクト・コード上の参照回数はリンカに-show=reference オプションを指定することで表示することができます。

(3)

領域

各領域はアドレス範囲によって3つに分けられます。

far領域は,saddr領域やnear領域を含む全領域となります。

(a)

saddr領域

アドレスが0xFFE20から0xFFF1Fまでの領域をsaddr領域と呼びます。

このアドレス範囲に配置したsaddr属性変数はサイズが最も小さい命令でアクセスします。

saddr領域は,特殊機能レジスタ(SFR)の一部や汎用レジスタも含みます。

SFRや汎用レジスタには変数を配置できません。

(b)

near領域

アドレスが0xF0000から0xFFE1Fまでの領域をnear領域と呼びます。

この領域には内部RAM,ミラー領域,データ・フラッシュ・メモリを含みます。

このアドレス範囲に配置したnear属性変数はsaddr領域に次いでサイズが小さい命令でアクセスします。

near領域は,拡張特殊機能レジスタ(2nd SFR)も含みます。

2nd SFRには変数を配置できません。

(c)

far領域

saddr領域やnear領域を含む全領域をfar領域と呼びます。

この領域には内部RAM以外のRAMやミラー領域以外のコード・フラッシュ・メモリ内の定数領域も含みます。

このアドレス範囲に配置したfar属性変数はサイズが最も大きい命令でアクセスします。

(4)

変数や定数を各領域に配置する方法

各変数や定数を含むセクションの配置アドレスをリンク・オプションを使って指定することによって,変数や定数を各領域に配置します。

例 1.

.saddr領域に配置するデフォルトのセクションは.sbssと.sdataです。
.sbssは初期値無のsaddr属性変数を配置するセクション,.sdataは初期値を持つsaddr属性変数を配置するセクションです。
ROMイメージを作成する時,.sdata を任意のアドレスに配置し,.sdata上のデータをRAMへ転送する場合の転送先セクションの名前を適当に決めます(以下では.sdataRとしています)。

-rom=.sdata=.sdataR
-start=.sdata/5000
-start=.sbss,.sdataR/ffe20

例 2.

near領域に配置するデフォルトのセクションは.bss,.data,および.constです。
.bssは初期値無のnear属性変数を配置するセクション,.dataは初期値を持つnear属性変数を配置するセクションです。
ROMイメージを作成する時,.dataを任意のアドレスに配置し,.data上のデータをRAMへ転送する場合の転送先セクションの名前を適当に決めます(以下では.dataRとしています)。
.constはnear属性定数を配置するセクションです。
near属性定数を配置する領域のアドレスはデバイスごとに決まっているのでアドレスはデバイスのユーザーズ・マニュアルを参照してください。



-rom=.data=.dataR
-start=.const/2000
-start=.data/4000
-start=.bss,.dataR/fe000

例 3.

far領域に配置するデフォルトのセクションは.bssf,.dataf,および.constfです。
RAMとして内部RAMのみを使うのであれば.bssfや.datafは通常は使いません。
そこで以下では.constfのみ説明します。
.constfはfar属性定数を配置するセクションです。
.constfはコード・フラッシュ・メモリ上に配置します。



-start=.constf/6000