現象:
unsigned char/short型変数を含む式が同一関数内で、A−B、B−A(A,B:当該変数を含む式)と同時に存在する場合、共通式削除の最適化により不当に拡張命令を削除する場合があります。
[例]
unsigned short var_a, var_b, var_c;
long result;
void f() {
unsigned short x;
if(var_a >= var_b) {
x = var_a-var_b;
result = x * var_c;
} else {
x = var_b - var_a;
result = x * var_c;
}
}
[出力コード]
_f:
MOV.L L14,R2 ; _var_a
MOV.L L14+4,R4 ; _var_b
MOV.W @R2,R5
MOV.W @R4,R2
MOV.L L14+8,R4 ; _var_c
MOV R5,R6
SUB R2,R6 ; temp <- var_a-var_b
MOV.W @R4,R7
EXTU.W R5,R5
EXTU.W R2,R2
CMP/GE R2,R5
BF/S L12
EXTU.W R7,R4
EXTU.W R6,R2 ; x <- (unsigned short)temp
MOV.L L14+12,R5 ; _result
MUL.L R2,R4
STS MACL,R2
RTS
MOV.L R2,@R5
L12:
EXTU.W R6,R6
MOV.L L14+12,R5 ; _result
NEG R6,R2 ; x <- (long)(-temp)
; EXTU.W R2,R2を不当に削除
MUL.L R2,R4
STS MACL,R2
RTS
MOV.L R2,@R5発生条件:
次の条件を全て満たす時、発生することがあります。
void f() {
unsigned short x;
long temp = var_a ‐ var_b;
if (var_a >= var_b) {
result = (unsigned short)temp * var_c;
/* var_a-var_b をtemp に置換 */
} else {
result = (unsigned short)(-temp) * var_c;
/* var_b-var_a を-temp に置換 */
}
}現象:
unsigned char/short型ポインタ変数のポインタ先と0との加減算もしくは1との乗算を行なう式を記述した場合、不当に変数のロード後のゼロ拡張命令を削除する場合があります。
[例]
unsigned char *p;
int a;
void func(){
a = 0;
a += *p;
}
[出力コード]
_func:
MOV.L L11,R5 ; _a
MOV #0,R2 ; H'00000000
MOV.L R2,@R5
MOV.L L11+4,R2 ; _p
MOV.L @R2,R6
MOV.B @R6,R2 ; ロード時に符号拡張
RTS
MOV.L R2,@R5 ; ゼロ拡張せずに4byte 領域にストア発生条件:
次の条件を全て満たす時、発生することがあります。
現象:
関数マクロ呼び出しを複数行にわたって記述し、その複数行の間に'//'コメントを行の1 カラム目から記述した場合に、 6001 インターナルエラーになります。
[例]
#define MACRO(a, b) a, b
void func() {
MACRO(1,0
// <- 1 カラム目から'//'コメント
);
}発生条件:
次の条件を全て満たす時、発生します。
現象:
C++言語の限定付名称を#pragmaに指定した場合に、4099インターナルエラーになる場合があります。ただし、コンパイル環境(ホストコンピュータのオペレーティングシステム)によって再現しないことがあります。
[例]
class cPRINT {
public:
static void IntPrint();
};
#pragma interrupt(cPRINT::IntPrint) /* 限定を含む名称の長さが4 の倍数 */
void cPRINT::IntPrint(){}発生条件:
次の条件を全て満たす時、発生することがあります。
現象:
align16オプション指定時に、関数の最後が条件式で、関数呼び出しで終わっている節が複数あり、当該関数の後に別関数が続いている場合、分岐先不正になるかもしくはアセンブラ、最適化リンケージエディタでエラーになる場合があります。
[例]
#include <stdio.h>
void g(
int a,
int b,
char *c);
void func(int x) {
switch (x){
case 0:
g(0, 0, NULL); /* 条件式の最後が関数呼び出し */
break;
default:
g(0, 1, NULL); /* 条件式の最後が関数呼び出し */
break;
}
}
main() { /* 別関数が続く */
func(0);
}発生条件:
次の条件を全て満たす時、発生することがあります。
現象:
cpu=sh1オプション以外指定時に比較を行った場合、DT命令を不正に生成、またはADD 命令を不正に移動する場合があります。
[例1]
struct tbl {
char bit:1;
}S,*Sp=&S;
char a,b;
func(){
int t;
t = S.bit == 0;
a = t << 1;
if (t != 0 ) b++;
}
[出力コード]
_func:
MOV.L L14,R6 ; _S
MOV.B @R6,R0
TST #128,R0
MOVT R6
; (A)へ命令が不当に移動
TST R0,R0 ; -> TST R2,R2
MOVT R2
MOV.L L14+4,R5 ; _a
SHLL R2
ADD # -1,R6 ; (A) 不当に移動
MOV.B R2,@R5
EXTS.B R6,R2 ; (A) 不当に移動
TST R2,R2
BF L12
MOV.L L14+8,R6 ; _b
MOV.B @R6,R2
ADD #1,R2
RTS
MOV.B R2,@R6
:
[例2]
char b;
func2(int c, char d) {
c = d - 1;
b = c << 1;
if(c != 0) {
b++;
}
}
[出力コード]
_func:
MOV.L L14+2,R6 ; _b
EXTS.B R5,R2
SHLL R4 ; d-1 ではなく引数のc をシフトしている
DT R2 ; c=d-1;およびc!=0 の判定を行っている
BT/S L12
MOV.B R4,@R6
ADD #1,R4
RTS
MOV.B R4,@R6
L12:
RTS
NOP発生条件:
次の条件(a)、(b)を満たし、かつ(c)または(d)を満たす時、発生することがあります。
現象:
1バイト、または2バイトデータを複合代入で左シフトした結果を参照した場合に、不当に符号拡張またはゼロ拡張命令を削除する場合があります。
[例]
short n;
void func(short s){
sub(s <<= n);
}
[出力コード]
_func:
STS.L PR,@-R15
MOV.L L11,R6 ; _n
MOV.W @R6,R1
MOV.L L11+4,R6 ; __sftl
JSR @R6
EXTS.W R4,R0
MOV.L L11+8,R2 ; _sub
MOV R0,R4 ; 演算結果が符号拡張されない
JMP @R2
LDS.L @R15+,PR発生条件:
次の条件を全て満たす時、発生することがあります。
現象:
unsignedの型の変数や式どうしの減算結果を、signedの型にキャストして比較する場合に、不正に符号なし比較命令で比較を行なう場合があります。
[例]
int test(unsigned int a, unsigned int b) {
if ((int)(a - b) < 0) {
return 1;
} else {
return 0;
}
}
[出力コード]
_test:
CMP/HS R5,R4 ; (unsigned int)a < (unsigned int)bで比較
MOVT R0
RTS
XOR #1,R0発生条件:
次の条件を全て満たす時、発生することがあります。
現象:
#pragma entryもしくは#pragma noregsaveを指定した場合、最適化リンケージエディタのレジスタ退避・回復最適化によりレジスタ退避・回復命令が不当に削除される場合があります。
発生条件:
次の条件を全て満たす時、発生することがあります。
現象:
符号付きビットフィールドの定数値比較('=='または'!=')において、定数値がビットフィールドの範囲を越えている場合に、比較結果が不正となる場合があります。
[例]
struct tbl {
unsigned int ib1:1;
int ib8:8;
} bf0 = {0,-2};
#include <stdio.h>
main() {
if (bf0.ib8 != 254) { /* 254(0xFE)を-2と判断してしまう */
printf("OK\n");
}
}発生条件:
次の条件(a)、(b)を満たし、かつ(c)、(d)、(e)のいずれかを満たした時、発生することがあります。
現象:
ループ内で符号なし変数を複数回参照した時、必要なゼロ拡張命令が削除される場合がある。
[例]
extern unsigned char X;
int sub(int a, int b, int n) {
int i, sum=0;
for (i = 0; i < n; i++) {
if (X == (unsigned char)0xff) { // Xの参照
sum += a;
}
if (X == (unsigned char)0xf0) { // Xの参照
sum += b;
}
X = X + 1; // Xの定義
}
return (sum);
}
[出力コード]
_sub:
MOV.L R12,@-R15
MOV.L R13,@-R15
MOV.L R14,@-R15
MOV R5,R13
MOV #0,R5
MOV.L L19,R1 ; _X
MOV R6,R7
MOV R4,R12
MOV R5,R6
MOV #-1,R4
MOV.B @R1,R2
; <- EXTU.B R2,R2が削除
MOV #-16,R14
EXTU.B R4,R4
BRA L11
EXTU.B R14,R14
L12:
CMP/EQ R4,R2 ; 比較結果が正しくない場合あり(X>127の時)
BF L14
ADD R12,R5
L14:
CMP/EQ R14,R2 ; 比較結果が正しくない場合あり(X>127の時)
BF L16
ADD R13,R5
L16:
ADD #1,R2
EXTU.B R2,R2
ADD #1,R6
L11:
CMP/GE R7,R6
BF L12
MOV.B R2,@R1
MOV R5,R0
MOV.L @R15+,R14
MOV.L @R15+,R13
RTS
MOV.L @R15+,R12発生条件:
次の(a)から(d)の条件、もしくは(e)から(h)の条件を全て満たす時、発生する可能性がある。
現象:
同じ値の浮動小数点定数を複数回使用した場合、不当に浮動小数点定数ロード式を削除する場合がある。
発生条件:
次の条件を全て満たす時、発生する可能性がある。
現象:
配列アクセスa[c-exp]において、cが定数、expの型がunsigned char/unsigned shortのとき、配列を正しくアクセスできない場合がある。
[例]
unsigned char dd[2];
void func(unsigned char a, unsigned char b) {
dd[15-a] = b;
}
[出力コード]
_func:
MOV.L L11,R2 ; _dd
NEG R4,R6 ; R6 <- -a
EXTU.B R6,R0 ; -aをゼロ拡張
ADD #15,R2
RTS
MOV.B R5,@(R0,R2) ; 異なるアドレスにアクセス発生条件:
次の条件を全て満たす時、発生する可能性がある。
現象:
memmoveライブラリ関数でメモリ領域を上位アドレスのメモリ領域に移動すると、指定した文字数以上の移動を行ってしまう。
発生条件:
次の条件を全て満たす時、発生する。
現象:
関数の最後の処理が条件文で、条件がネストしており、かつ最後の条件節が関数呼び出し+return文、その前の条件節が関数呼び出しで終わっている場合、関数出口への無条件分岐が不当に削除される場合がある。
[例]
void sub(int parm) {
if (parm == 0) {
;
} else if (parm == 1) {
;
} else if (parm == 2) {
;
} else if (parm == 3) {
;
} else if (parm == 4) {
;
} else if (parm == 5) {
func1(); /* <A> */
} else {
func2(); /* <B> */
return; /* <B> */
}
return;
}
[出力コード]
_sub:
STS.L PR,@-R15
TST R4,R4
BT L11
MOV R4,R0
CMP/EQ #1,R0
BT L11
CMP/EQ #2,R0
BT L11
CMP/EQ #3,R0
BT L11
CMP/EQ #4,R0
BT L11
CMP/EQ #5,R0
BF L18
MOV.L L20+2,R2 ; _func1
JSR @R2
NOP
L11:
; L19への分岐命令を削除
L18:
MOV.L L20+6,R2 ; _func2
JMP @R2 ; 常に関数呼び出しされる
LDS.L @R15+,PR
L19:
LDS.L @R15+,PR
RTS
NOP発生条件:
次の条件を全て満たす時、発生する可能性がある。
現象:
unsigned型の変数をfloat型に明示的にキャストした時、キャストが不当に削除される場合がある。
[例]
unsigned short us1;
volatile unsigned short us0;
volatile float f0;
float *p;
void func() {
f0 = *p = ((float)us0, (float)us1);
}
[出力コード]
_func:
MOV.L L29+50,R2 ; _us0
MOV.L L29+54,R5 ; _p
MOV.W @R2,R6
MOV.L L29+58,R6 ; _us1
MOV.W @R6,R2
EXTU.W R2,R6
MOV.L @R5,R2
MOV.L R6,@R2 ; floatに変換しないで*pにストア
MOV.L @R5,R2
MOV.L @R2,R6
MOV.L L29+10,R2 ; _f0
RTS
MOV.L R6,@R2 ; floatに変換しないでf0にストア発生条件:
次のいずれかの条件を満たす時、発生する可能性がある。
現象:
SH-4でld_exp()またはst_ext()組み込み関数使用時にパラメータにローカル配列を指定した場合、不正にスタックポインタを移動するコードを出力する場合がある。
[例]
#include <machine.h>
void main() {
float table[4][4], data1[4][4], data2[4][4];
:
ld_ext(table);
mtrx4mul(data1,data2);
:
}
[出力コード]
:
FRCHG
FMOV.S @R15+,FR0 ; R15を更新、この間で例外が発生した場合
上位のスタック領域が破壊
FMOV.S @R15+,FR1 ; |
FMOV.S @R15+,FR2 ; |
FMOV.S @R15+,FR3 ; |
FMOV.S @R15+,FR4 ; |
FMOV.S @R15+,FR5 ; |
FMOV.S @R15+,FR6 ; |
FMOV.S @R15+,FR7 ; |
FMOV.S @R15+,FR8 ; |
FMOV.S @R15+,FR9 ; |
FMOV.S @R15+,FR10 ; |
FMOV.S @R15+,FR11 ; |
FMOV.S @R15+,FR12 ; |
FMOV.S @R15+,FR13 ; |
FMOV.S @R15+,FR14 ; |
FMOV.S @R15+,FR15 ; |
FRCHG ; |
ADD #-64,R15 ; V
:発生条件:
次の条件を全て満たす時、発生する可能性がある。
現象:
"シンボルアドレス+オフセット値"の初期値をもつ変数が多く存在する場合、内部エラー(4098)もしくはオブジェクト不正になる場合がある。
発生条件:
次の条件を全て満たす時、発生する可能性がある。
[例]
extern char g;
#define DATA1A (&g+2147483647)
#define DATA10A DATA1A, DATA1A, DATA1A, DATA1A, DATA1A,\
DATA1A, DATA1A, DATA1A, DATA1A, DATA1A
#define DATA100A DATA10A, DATA10A, DATA10A, DATA10A, DATA10A,\
DATA10A, DATA10A, DATA10A, DATA10A, DATA10A
/* 以下は(変数の数+offsetの合計桁数)=(3001+10*3001)=33011>33000となる */
char *a1[1000] = {
DATA100A, DATA100A, DATA100A, DATA100A, DATA100A,
DATA100A, DATA100A, DATA100A, DATA100A, DATA100A
};
char *a2[1000] = {
DATA100A, DATA100A, DATA100A, DATA100A, DATA100A,
DATA100A, DATA100A, DATA100A, DATA100A, DATA100A
};
char *a3[1000] = {
DATA100A, DATA100A, DATA100A, DATA100A, DATA100A,
DATA100A, DATA100A, DATA100A, DATA100A, DATA100A
};
char *a = DATA1A;現象:
ループ内にsigned型の変数iからunsigned型の変数vの減算i=i-vがあるとき、不当にゼロ拡張を行なう。
[例]
int i = 319;
unsigned char v = 97;
main()
{
int f;
for(f=0; f<5; f++){
i = i - v; /* -vの結果がゼロ拡張されて演算される。*/
}
}発生条件:
次の条件を全て満たす時、発生する可能性がある。
現象:
char/short 型への型変換を行なった直後に浮動小数点型への型変換を行なうと、char/shortへの変換が行なわれない。
[例]
unsigned short US = 256;
int I;
float F;
main(){
char c;
c = US; /* short型変数をchar型変数に型変換 */
I = 3 & c; /* char 型変数がレジスタに割り付く */
F = c; /* char 型から float 型への型変換 */
}
[出力コード]
_main:
MOV.L _US,R6
MOV.L _I,R5
MOV.W @R6,R0 /* 256 -> R0 char型への型変換EXTUが出力されない */
LDS R0,FPUL /* 256のままfloatに変換している */
:発生条件:
次の条件を全て満たす時、発生する可能性がある。
現象:
cpu=sh4を指定してコンパイルした場合にFPSCRの設定コードをこえて不当にFPU命令をループ外に移動する。
[例]
double dd;
struct tag {
short aa;
long bb;
char cc:5;
} str;
main()
{
int i;
str.bb = 10;
str.aa = 10;
for(i=5; i>=0; i--){
str.cc = str.aa++;
dd = str.bb;
}
}
[出力コード]
_main:
MOV.L R14,@-R15
MOV #10,R5 ; H'0000000A
MOV.L L13+2,R2 ; _dd
LDS R5,FPUL
MOV.L L13+6,R7 ; _str
FLOAT FPUL,DR8 ; LDS R2 FPSCRをまたいでループ外に移動
ADD #8,R2
MOV #8,R1 ; H'00000008
:
L11:
MOV.B @(8,R7),R0
MOV R0,R6
:
DT R4
OR R1,R2
LDS R2,FPSCR
; FLOAT FPUL,DR8 移動前の位置
ADD #1,R5
:発生条件:
次の条件を全て満たす時、発生する可能性がある。
現象:
最内側ループで割付けられたレジスタの内容が、そのループ内で破壊される。
[例]
複数の変数に対して同じレジスタを割り付けてしまいレジスタ内容が破壊されている。
for(i1 = 0; i1 < max1 ; i1++) {
a = b;
for(i2 = 0; i2 < max2 ; i2++) { /* (イ) */
c = x + b; /* (ロ) */
} /* (ハ) */
ans = a + c;
}
[出力コード]
MOV.L @(R0,R15),R5 ;a にR5が割り付いている
:
MOV.L R5,@(R0,R15) ;aの退避
: ;ループ入口(イ)
MOV.L @(R0,R15),R5 ;c にR5を割り付けた
:
L1:
: ;ループ本体(ロ)(a の参照無し)
MOV Rn,R5 ; c = x + b の結果をR5に格納
:
BF L1
: ;ループ出口(ハ)
MOV.L @(R0,R15),R5 ;cを退避せずにR5を上書き
:
MOV.L R5,Rn ;破壊されたc の値をロードしている発生条件:
次の条件を全て満たす時、発生する可能性がある。
現象:
double/float切り替えコードが2つ出力されるとき、2回目のFPSCRロードが不正に削除される。
[例]
double d0;
float f0, f1, f2;
main
{
int i;
for(i = 0; i < 100; i++){
d0++;
f1 = f1 + f0;
}
}
[出力コード]
_main: ; function: main
MOV.L L13+2,R1 ; _d0
MOVA L13+6,R0
:
L11:
STS FPSCR,R2
DT R6
OR R5,R2
LDS R2,FPSCR
FADD DR4,DR6 ; <--この後にSTS FPSCR,R2が必要
AND R4,R2
LDS R2,FPSCR
BF/S L11
FADD FR9,FR8
ADD #8,R1
:発生条件:
次の条件を全て満たす時、発生する可能性がある。
現象:
戻り値を参照しない実行時ルーチンの引数に対して必要な符号拡張が行われない。
[例]
実行時ルーチン(__itod_a)への引数(unsigned long int) R0 に
cを符号拡張した値を渡していない。
double D;
int I;
unsigned short US = 256;
func2(){
char c;
c = US;
I = 3 & c;
D = c;
}
[出力コード]
_func2:
STS.L PR,@-R15
ADD #-12,R15
MOV.L L20,R6 ; _US
MOV.L L20+4,R5 ; _I
MOV.W @R6,R2
MOV.L L20+16,R6 ; _D
MOV R2,R0
AND #3,R0
MOV.L R6,@R15
MOV.L L20+20,R6 ; __itod_a
MOV.L R0,@R5 ; <--この後に EXTS.B R2,R2が必要
JSR @R6
MOV R2,R0発生条件:
次の条件を満たす時、発生する可能性がある。
現象:
ポインタを介して2次元以上の構造体配列のある要素のメンバを参照したとき、そのメンバへ設定/参照が正しく行なわれない。
[例]
typedef struct {
int aaa;
} ST;
void main()
{
((ST (*)[2])0x10000)[0]->aaa = 100;
/* 0x10000[0][0].aaaへの設定が正しく行われない */
}発生条件:
次の条件を全て満たす時、発生する可能性がある。
現象:
latin1を指定してコンパイルした際に、一部正常なlatin1コードに対して不当にエラーメッセージを出力する。
現象:
割り込み関数のスタックサイズ情報(リスティングファイル/アセンブリソースのスタックフレームサイズ)に、CPUが暗黙的に使用するPCとSRの退避分が含まれていない。
発生条件:
次の条件を全て満たす時、発生する可能性がある。