ページの本文へ

Hitachi
お問い合わせお問い合わせ

SH C/C++コンパイラ Ver.7.1.01-Ver.7.1.03で対策した制限事項

 

SH C/C++コンパイラ Ver.7.1.03で対策した制限事項

1. NEG命令後の不当拡張命令削除

現象:

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

発生条件:

次の条件を全て満たす時、発生することがあります。

(a)
optimize=1を指定している。
(b)
unsigned char/short型変数を使用している。
(c)
(b)の変数を含む式が同一関数内で以下の演算で使用されている。
A−B
B−A
A、Bは(b)の変数を含む式
上の例では、A :var_a 、B :var_b
(d)
共通式削除の最適化により、(c)の演算が共通化される。
  上の例では、以下のとおり。
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 に置換 */
    }
}

2. ポインタ変数ロード後の不当拡張命令削除

現象:

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 領域にストア

発生条件:

次の条件を全て満たす時、発生することがあります。

(a)
optimize=1を指定している。
(b)
unsigned char/short型変数をポインタを介して使用している。
(c)
(b)の変数と0の加減算もしくは1との乗算を行っている(最適化により0との加減算もしくは1との乗算になる場合もあり)。

3. マクロ呼び出しでのインターナルエラー

現象:

関数マクロ呼び出しを複数行にわたって記述し、その複数行の間に'//'コメントを行の1 カラム目から記述した場合に、 6001 インターナルエラーになります。

[例]
#define MACRO(a, b) a, b
void func() {
    MACRO(1,0
// <- 1 カラム目から'//'コメント
    );
}

発生条件:

次の条件を全て満たす時、発生します。

(a)
listfileオプションを指定している。
(b)
関数マクロ呼び出しがある。
(c)
関数マクロ呼び出し中に1 カラム目から'//'コメントを記述している。

4. C++限定付名称を#pragmaに指定時のインターナルエラー

現象:

C++言語の限定付名称を#pragmaに指定した場合に、4099インターナルエラーになる場合があります。ただし、コンパイル環境(ホストコンピュータのオペレーティングシステム)によって再現しないことがあります。

[例]
class cPRINT {
public:
    static void IntPrint();
};
#pragma interrupt(cPRINT::IntPrint) /* 限定を含む名称の長さが4 の倍数 */
void cPRINT::IntPrint(){}

発生条件:

次の条件を全て満たす時、発生することがあります。

(a)
C++言語を使用している。
(b)
#pragma指定に限定付名称を指定している。
(c)
限定を含む名称の長さが4の倍数である。

5. align16指定時の不当分岐(Ver.7.1.02 のみ)

現象:

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);
}

発生条件:

次の条件を全て満たす時、発生することがあります。

(a)
optimize=1を指定している。
(b)
align16オプションを指定している。
(c)
関数の最後が条件式であり、その条件式に複数の節がある。
(d)
(c)の節のすべてが関数呼び出しで終わっている。
(e)
当該関数の後に別関数が続いている。

6. DT命令の不当生成

現象:

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)を満たす時、発生することがあります。

(a)
optimize=1を指定している。
(b)
cpuオプションにsh1以外を指定している。
(c)
ビットフィールドの0 との'=='比較、もしくは'!='比較を行った後、その比較結果を再度比較している(例1)。
(d)
加算結果を異なる型の変数に代入して(または異なる型にキャストして)比較を行っている(例2)。

7. 左シフト時の不当拡張命令削除

現象:

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

発生条件:

次の条件を全て満たす時、発生することがあります。

(a)
cpu=sh1|sh2|sh2eオプションを指定している。
(b)
unsigned/signed char/short型データを左シフトで複合代入している。
(c)
複合代入した結果をシフトするデータの型よりも大きな型に代入している。
例えば、int型の変数への代入や、パラメタとしての使用している場合。
(d)
複合代入した結果が、そのシフト以降で使用されない。
(e)
シフト数が変数である。

8. 符号なし式の減算結果比較不正

現象:

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

発生条件:

次の条件を全て満たす時、発生することがあります。

(a)
unsignedの型の整数同士の減算の結果を、同じサイズのsignedの型にキャストしてから比較している。
(b)
減算結果をキャストした値が負である。

9. #pragma entry|noregsave指定時のレジスタ退避・回復不正

現象:

#pragma entryもしくは#pragma noregsaveを指定した場合、最適化リンケージエディタのレジスタ退避・回復最適化によりレジスタ退避・回復命令が不当に削除される場合があります。

発生条件:

次の条件を全て満たす時、発生することがあります。

(a)
code=machinecodeオプションを指定している。
(b)
goptimizeオプションを指定している。
(c)
#pragma entryもしくは#pragma noregsaveを指定している関数内で、関数を呼び出している。
(d)
最適化リンケージエディタでoptimize=registerオプションを指定している。

10. 符号付きビットフィールドの範囲外定数値比較不正

現象:

符号付きビットフィールドの定数値比較('=='または'!=')において、定数値がビットフィールドの範囲を越えている場合に、比較結果が不正となる場合があります。

[例]
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)のいずれかを満たした時、発生することがあります。

(a)
符号付きビットフィールド(2 〜31bit)の定数値比較('=='または'!=')を行っている。
(b)
(a)の定数値が符号付きビットフィールドの範囲外であり、かつ最大値の2倍以下であり、かつ最小値の2倍より大きい。
例:8bitのビットフィールドの場合、-255〜-129または128〜254の範囲
(c)
ビットフィールドのサイズが8bitでも16bitでもない。
(d)
サイズが8bitのビットフィールドであり、そのビットオフセットが8、16、24ビットではない。
(e)
サイズが16bitのビットフィールドであり、そのビットオフセットが16ビットではない。
 

SH C/C++コンパイラ Ver.7.1.02で対策した制限事項

1. ゼロ拡張命令の不当削除

現象:

ループ内で符号なし変数を複数回参照した時、必要なゼロ拡張命令が削除される場合がある。

[例]
  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)
optimize=1を指定している。
(b)
unsigned char/unsigned short型変数を使用している。
(c)
(b)の変数がループ内で2回以上参照した後、定義されている(例参照)。
(d)
(b)の変数が最初の参照前にメモリからロードされる。
(e)
optimize=1を指定している。
(f)
unsigned char/unsigned short型ローカル変数を使用している。
(g)
(f)の変数がループ内で右シフトのシフト元変数として使用されている。
(h)
(g)のシフト数が2以上である(SHLR2/SHLR8/SHLR16に展開される)。

2. 浮動小数点定数ロードの不当削除

現象:

同じ値の浮動小数点定数を複数回使用した場合、不当に浮動小数点定数ロード式を削除する場合がある。

発生条件:

次の条件を全て満たす時、発生する可能性がある。

(a)
optimize=1を指定している。
(b)
同じ値の浮動小数点定数をループ内で2回以上使用している。
(c)
(b)と同じ値の定数をループ外で使用している。

3. 配列アクセス不正

現象:

配列アクセス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) ; 異なるアドレスにアクセス

発生条件:

次の条件を全て満たす時、発生する可能性がある。

(a)
optimize=1を指定している。
(b)
配列の要素を"定数-式(unsigned char/unsigned short)"でアクセスしている(例ではdd[15-a])。

4. memmoveライブラリ不正

現象:

memmoveライブラリ関数でメモリ領域を上位アドレスのメモリ領域に移動すると、指定した文字数以上の移動を行ってしまう。

発生条件:

次の条件を全て満たす時、発生する。

(a)
移動サイズが31byte以上である。
(b)
移動先アドレスが移動元アドレスより大きい(メモリ上位へ移動)。
(c)
(移動元アドレス+移動サイズ)が移動先領域内にある(移動領域に重なりがある)。
(d)
移動先アドレス、移動元アドレスのどちらかが4の倍数でない。

5. 無条件分岐の不当削除

現象:

関数の最後の処理が条件文で、条件がネストしており、かつ最後の条件節が関数呼び出し+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

発生条件:

次の条件を全て満たす時、発生する可能性がある。

(a)
optimize=1を指定している。
(b)
関数の最後の処理が条件文でかつ条件がネストしている。
(c)
最後の条件節が関数呼び出し+return文で終わっている(例の<B>)。
(d)
(c)の直前の条件節が関数呼び出しで終わっている(例の<A>)。

6. unsigned型->float型キャスト不正

現象:

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にストア

発生条件:

次のいずれかの条件を満たす時、発生する可能性がある。

(a)
unsigned型の変数をfloat型にキャストしている。
(b)
unsigned型の変数をdouble型にキャストし、かつdouble=floatまたはfpu=singleオプションを指定、またはlong double型にキャストし、かつfpu=singleを指定している。

7. ld_ext()、st_ext()使用時のスタックポインタ不正移動

現象:

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
                :

発生条件:

次の条件を全て満たす時、発生する可能性がある。

(a)
cpu=sh4を指定し、かつld_ext()、st_ext()を使用している。
(b)
ld_ext(),st_ext()のパラメタにローカル配列を指定している。

8. データ出力時不正

現象:

"シンボルアドレス+オフセット値"の初期値をもつ変数が多く存在する場合、内部エラー(4098)もしくはオブジェクト不正になる場合がある。

発生条件:

次の条件を全て満たす時、発生する可能性がある。

(a)
code=machinecode(デフォルト)を指定している。
(b)
listfileオプションを指定していない、もしくはlistfileオプションとshow=noobjectオプションを同時に指定している。
(c)
初期値つき変数の定義が存在する。
(d)
(c)の初期値が"シンボルアドレス+オフセット値"または構造体先頭でないメンバのアドレスである。
(e)
(c)の変数、および初期値が以下の条件を満たしている。
((c)の数+(4)のオフセット値の10進桁数の合計)≧33000
[例]
    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;

 

SH C/C++コンパイラ Ver.7.1.01で対策した制限事項

1. ループ内での不当ゼロ拡張生成

現象:

ループ内に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の結果がゼロ拡張されて演算される。*/
      }
  }

発生条件:

次の条件を全て満たす時、発生する可能性がある。

(a)
optimize=1を指定する。
(b)
ループ内にsigned型の変数iからunsigned型の変数vの減算i = i - vがある。
(c)
変数iの型は4バイト(signed int, signed long)。
(d)
変数vの型は4バイト未満のunsigned型(unsigned char/short)。
(e)
変数vはループ内不変式である。

2. 型変換不正

現象:

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に変換している */
        :

発生条件:

次の条件を全て満たす時、発生する可能性がある。

(a)
CPUにSH2EまたはSH4を指定している。
(b)
char/short型にそれより大きな型から型変換を行なう。
(c)
(b)の変換前の値が変換後の型の範囲を超えている。
(d)
(b)の変換後の変数を浮動小数点型に型変換している。
(e)
(b)の変換後の値がレジスタに割りついている。

3. FPSCR設定コードをこえての命令不当移動

現象:

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
        :

発生条件:

次の条件を全て満たす時、発生する可能性がある。

(a)
optimize=1を指定している。
(b)
CPUにSH4を指定している。
(c)
fpuオプションを指定していない。
(d)
ループ内にdouble型の演算がある。
(e)
(d)の演算がループ内不変式となる。

4. ループでのレジスタ割付不正

現象:

最内側ループで割付けられたレジスタの内容が、そのループ内で破壊される。

[例]
複数の変数に対して同じレジスタを割り付けてしまいレジスタ内容が破壊されている。
  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 の値をロードしている

発生条件:

次の条件を全て満たす時、発生する可能性がある。

(a)
optimize=1を指定している。
(b)
最内側ループ内にレジスタ割り付け対象の変数がある。(例の場合は変数c)
(c)
(b)の変数を含む式がループの外にありその同じ式にある変数(例の場合は変数a)に(b)の変数と同じレジスタが割り付く。(例の場合はR5レジスタ)

5. FPSCRロード不当削除

現象:

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
          :

発生条件:

次の条件を全て満たす時、発生する可能性がある。

(a)
optimize=1を指定している。
(b)
CPUにSH4を指定している。
(c)
fpuオプションを指定していない。
(d)
doubleおよびfloat型の演算がある。

6. 関数コール引数の符号拡張不正

現象:

戻り値を参照しない実行時ルーチンの引数に対して必要な符号拡張が行われない。

[例] 
 実行時ルーチン(__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

発生条件:

次の条件を満たす時、発生する可能性がある。

(a)
実行時ルーチン_itod_a、_utod_aを使用していて、その関数の引数は4バイトで、char/shortの型の変数を引数に渡している。

7. 構造体メンバ設定/参照不正

現象:

ポインタを介して2次元以上の構造体配列のある要素のメンバを参照したとき、そのメンバへ設定/参照が正しく行なわれない。

[例]
  typedef struct {
      int aaa;
  } ST;
  void main()
  {
      ((ST (*)[2])0x10000)[0]->aaa = 100;
           /* 0x10000[0][0].aaaへの設定が正しく行われない */
  }

発生条件:

次の条件を全て満たす時、発生する可能性がある。

(a)
2次元以上の構造体配列がある。
(b)
ポインタを介して(a)の構造体配列のメンバを設定/参照している。

8. latin1指定時不当なエラー出力

現象:

latin1を指定してコンパイルした際に、一部正常なlatin1コードに対して不当にエラーメッセージを出力する。

9. スタックサイズ表示不正

現象:

割り込み関数のスタックサイズ情報(リスティングファイル/アセンブリソースのスタックフレームサイズ)に、CPUが暗黙的に使用するPCとSRの退避分が含まれていない。

発生条件:

次の条件を全て満たす時、発生する可能性がある。

(a)
CPUにSH1/SH2/SH2Eが指定されている。
(b)
#pragma interrupt指定で指定した割込み関数がある。

お問い合わせ

本件に関する詳細について、フォームからお問い合わせいただけます。

お問い合わせフォーム