228
Copyright © 1999-2001 ARM Limited. All rights reserved. ARM DUI0056DJ-00 ARM ® デベロッパスイート バージョン バージョン バージョン バージョン 1.2 デベロッパガイド デベロッパガイド デベロッパガイド デベロッパガイド

ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

  • Upload
    others

  • View
    4

  • Download
    0

Embed Size (px)

Citation preview

Page 1: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

Copyright © 1999-2001 ARM Limited. All rights reserved.ARM DUI0056DJ-00

ARM®

デベロッパスイートバージョンバージョンバージョンバージョン 1.2

デベロッパガイドデベロッパガイドデベロッパガイドデベロッパガイド

Page 2: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

ii Copyright © 1999-2001 ARM Limited. All rights reserved. ARM DUI0056DJ-00

ARMデベロッパスイートデベロッパスイートデベロッパスイートデベロッパスイートデベロッパガイドデベロッパガイドデベロッパガイドデベロッパガイド

Copyright © 1999-2001 ARM Limited. All rights reserved.

リリース情報リリース情報リリース情報リリース情報

本書の改訂履歴は以下の通りです。

著作権著作権著作権著作権

®または™のマークが付いた言葉およびロゴは、ARM Limitedが所有する登録商標または商標です。本書に記載されている他の製品名は、各社の所有する商標です。

本書に記載されている情報の全部または一部、ならびに本書で紹介する製品は、著作権所有者の

文書による事前の許可を得ない限り、転用・複製することを禁じます。

本書に記載されている製品は、今後も継続的に開発・改良の対象となります。本書に含まれる製

品およびその利用方法についての情報は、ARMが利用者の利益のために提供するものです。したがって当社では、製品の市販性または利用の適切性を含め、暗示的・明示的に関係なく一切の責

任を負いません。

本書は、本製品の利用者をサポートすることだけを目的としています。本書に記載されている情

報の使用、情報の誤りまたは省略、あるいは本製品の誤使用によって発生したいかなる損失・損

傷についても、ARM Limitedは一切責任を負いません。

改訂履歴改訂履歴改訂履歴改訂履歴

日付日付日付日付 発行発行発行発行 変更内容変更内容変更内容変更内容

1999年 10月 A リリース 1.0

2000年 3月 B リリース 1.0.1

2000年 11月 C リリース 1.1

2001年 11月 D リリース 1.2

Page 3: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

ARM DUI0056DJ-00 Copyright © 1999-2001 ARM Limited. All rights reserved. iii

目次ARMデベロッパスイートデベロッパガイドデベロッパスイートデベロッパガイドデベロッパスイートデベロッパガイドデベロッパスイートデベロッパガイド

序章序章序章序章本書について ................................................................................................. viiiご意見・ご質問 ...............................................................................................xii

第第第第 1章章章章 はじめにはじめにはじめにはじめに1.1 ARMデベロッパガイドについて ..................................................................1-21.2 プログラミングに関する一般事項 ................................................................1-41.3 ARMをターゲットとした開発......................................................................1-5

第第第第 2章章章章 プロシージャコール標準の使用プロシージャコール標準の使用プロシージャコール標準の使用プロシージャコール標準の使用2.1 ARM-Thumbプロシージャコール標準について...........................................2-22.2 レジスタの役割と名前 ..................................................................................2-42.3 スタック........................................................................................................2-62.4 パラメータの受け渡し ..................................................................................2-92.5 スタックリミットチェック ......................................................................... 2-112.6 読み出し専用位置独立 ................................................................................ 2-142.7 読み出し /書き込み位置独立 ...................................................................... 2-152.8 ARM状態と Thumb状態間のインターワーキング..................................... 2-162.9 浮動小数点オプション ................................................................................ 2-17

第第第第 3章章章章 ARMとととと Thumbのインターワーキングのインターワーキングのインターワーキングのインターワーキング3.1 インターワーキングについて .......................................................................3-2

Page 4: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

目次

iv Copyright © 1999-2001 ARM Limited. All rights reserved. ARM DUI0056DJ-00

3.2 アセンブリ言語のインターワーキング ........................................................ 3-63.3 Cと C++のインターワーキングおよびベニア .......................................... 3-113.4 ベニアを使用したアセンブリ言語のインターワーキング.......................... 3-15

第第第第 4章章章章 C、、、、C++、アセンブリ言語の混合、アセンブリ言語の混合、アセンブリ言語の混合、アセンブリ言語の混合4.1 インラインアセンブラの使用....................................................................... 4-24.2 アセンブリコードから Cグローバル変数へのアクセス ............................ 4-154.3 C++からの Cヘッダファイルの使用......................................................... 4-164.4 C、C++、アセンブリ言語間の呼び出し .................................................... 4-18

第第第第 5章章章章 プロセッサ例外処理プロセッサ例外処理プロセッサ例外処理プロセッサ例外処理5.1 プロセッサ例外について .............................................................................. 5-25.2 例外の開始と終了......................................................................................... 5-55.3 例外ハンドラのインストール....................................................................... 5-95.4 SWIハンドラ ............................................................................................. 5-145.5 割り込みハンドラ....................................................................................... 5-235.6 リセットハンドラ....................................................................................... 5-335.7 未定義命令ハンドラ ................................................................................... 5-345.8 プリフェッチアボートハンドラ ................................................................. 5-355.9 データアボートハンドラ ............................................................................ 5-365.10 例外ハンドラのチェインニング ................................................................. 5-385.11 Thumb対応プロセッサでの例外処理......................................................... 5-405.12 システムモード .......................................................................................... 5-45

第第第第 6章章章章 ROMコードの記述コードの記述コードの記述コードの記述6.1 ROMコードの記述について ........................................................................ 6-26.2 メモリマップに関する注意点....................................................................... 6-46.3 システムの初期化......................................................................................... 6-76.4 セミホスティングを使用した Cの基本サンプル ....................................... 6-116.5 アドレス 0への ROMイメージのロード ................................................... 6-146.6 分散ローディングと再マッピングの使用................................................... 6-256.7 セミホステッドアプリケーションの割り込み処理 .................................... 6-296.8 組み込みアプリケーションの割り込み処理 ............................................... 6-346.9 メモリマップ I/Oを使用した分散ローディング......................................... 6-376.10 トラブルシューティング ............................................................................ 6-446.11 コードサイズとデータサイズの測定 .......................................................... 6-47

第第第第 7章章章章 キャッシュと密結合メモリキャッシュと密結合メモリキャッシュと密結合メモリキャッシュと密結合メモリ7.1 キャッシュおよび密結合メモリについて..................................................... 7-27.2 システム制御コプロセッサ .......................................................................... 7-47.3 メモリ保護ユニット ..................................................................................... 7-57.4 PUの構成 ..................................................................................................... 7-77.5 メモリ管理ユニット ................................................................................... 7-127.6 MMUの構成 ............................................................................................... 7-167.7 密結合メモリ .............................................................................................. 7-19

Page 5: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

目次

ARM DUI0056DJ-00 Copyright © 1999-2001 ARM Limited. All rights reserved. v

第第第第 8章章章章 デバッグ通信チャネルデバッグ通信チャネルデバッグ通信チャネルデバッグ通信チャネル8.1 デバッグ通信チャネルについて....................................................................8-28.2 コマンドラインデバッギングコマンド .........................................................8-38.3 通信チャネルビューのイネーブル ................................................................8-48.4 ターゲットのデータ転送 ..............................................................................8-58.5 デバッグ通信のポーリング ...........................................................................8-68.6 割り込み駆動型デバッグ通信 .....................................................................8-128.7 Thumb状態からのアクセス........................................................................ 8-138.8 セミホスティング ....................................................................................... 8-14

用語集用語集用語集用語集

Page 6: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

目次

vi Copyright © 1999-2001 ARM Limited. All rights reserved. ARM DUI0056DJ-00

Page 7: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

ARM DUI0056DJ-00 Copyright © 1999-2001 ARM Limited. All rights reserved. vii

序章序章序章序章

本章では、ARM デベロッパスイート(ADS)のデベロッパガイド(本書)について概説します。本章は以下のセクションから構成されています。

• 本書について:P. viii

• ご意見・ご質問:P. xii

Page 8: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

序章

viii Copyright © 1999-2001 ARM Limited. All rights reserved. ARM DUI0056DJ-00

本書について本書について本書について本書について

本書では、ARM プロセッサファミリ向けのコードの記述に関する参考情報を提供し

ます。

対象読者対象読者対象読者対象読者

本書はARMプロセッサファミリ向けのコードを記述する全ての開発者を対象としています。したがって本書の内容は、ADS「スタートアップガイド」に記載されている ARM開発ツールを熟知した経験豊富なソフトウェア開発者を想定して書かれています。

本書の構成本書の構成本書の構成本書の構成

本書は以下の章から構成されています。

第第第第 1章章章章 はじめに

ARMデベロッパスイート(ADS)について概説します。

第第第第 2章章章章 プロシージャコール標準の使用

ARM/Thumb® プロシージャコール標準の使用方法について説明します。

このプロシージャコール標準を使用することにより、コンパイルまたはアセンブルを別々に行ったモジュールをより簡単に統合することができます。

第第第第 3章章章章 ARMと Thumbのインターワーキング

Thumb命令セット実装プロセッサ向けのコードを記述する際の、ARM状態と Thumb状態の切り替え方法について説明します。

第第第第 4章章章章 C、C++、アセンブリ言語の混合

C、C++、ARMアセンブリ言語の混合コードの記述方法と、Cおよび C++からの ARMインラインアセンブラの使用方法について説明します。

第第第第 5章章章章 プロセッサ例外処理

ARM プロセッサがサポートしている各種例外の処理方法について説明

します。

第第第第 6章章章章 ROMコードの記述

ROMイメージのビルド方法について説明します。これらのイメージは組み込みアプリケーションなどで使用することができます。また、ROMコードを記述する際に最も犯しやすい誤りを回避するためのヒントも記載しています。

Page 9: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

序章

ARM DUI0056DJ-00 Copyright © 1999-2001 ARM Limited. All rights reserved. ix

第第第第 7章章章章 キャッシュと密結合メモリ

ARMシステムのキャッシュと密結合メモリについて説明します。

第第第第 8章章章章 デバッグ通信チャネル

デバッグ通信チャネル(DCC)の使用方法について説明します。

表記規則表記規則表記規則表記規則

本書では以下の表記規則を使用しています。

monospace コマンド、ファイル名、プログラム名、ソースコードなど、キーボード

から入力可能なテキストを示しています。

monospace コマンドまたはオプションに使用可能な略語を示しています。コマンド

名またはオプション名を全て入力する代わりに、下線部分の文字だけを入力してこれらを指定することができます。

monospace italic

コマンドまたは関数への引数で、特定の値に置き換えることが可能なものを示しています。

monospace bold

サンプルコード以外に使用される言語キーワードを示しています。

italic 重要用語、専門用語、相互参照、引用箇所を斜体で記載しています。

bold メニュー名などのインタフェース要素を太字で記載しています。また、

必要に応じて記述リスト内の重要箇所や ARM プロセッサのシグナル名

にも太字を使用しています。

参考資料参考資料参考資料参考資料

ここでは、ARMプロセッサファミリ向け開発コードに関する補足情報を記載したARMLimitedおよび各社の出版物を紹介します。

ARMは自社出版物の定期的な更新・修正を行っています。最新の正誤表および追補表については、http://www.arm.comをご覧下さい。

また、よくある質問とその答えをまとめた FAQリストを以下のサイトでご覧頂けます。http://www.arm.com/DevSupp/Sales+Support/faq.html

Page 10: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

序章

x Copyright © 1999-2001 ARM Limited. All rights reserved. ARM DUI0056DJ-00

ARMの出版物の出版物の出版物の出版物

本書は、ARMプロセッサファミリ向けアプリケーション開発に関する一般的な情報を提供するものです。ADS のコンポーネントに関しては、ADS 1.2 の以下の付属資料を参照して下さい。

• ADSインストール /ライセンス管理ガイド(ARM DUI 0139)

• ADSアセンブラガイド(ARM DUI 0068)

• CodeWarrior IDE Guide(ARM DUI 0065)

• ADSコンパイラ /ライブラリガイド(ARM DUI 0067)

• ADSリンカ /ユーティリティガイド(ARM DUI 0151)

• AXD/armsdデバッガガイド(ARM DUI 0066)

• ADSデバッグターゲットガイド(ARM DUI 0058)

• スタートアップガイド(ARM DUI 0064)

ARMデベロッパスイートには上記の他に以下の文書も収録されています。

• ARM Architecture Reference Manual(ARM DDI 0100)。この資料は DynaTextと PDF形式で提供しています。

• ARM アプリケーションライブラリプログラマガイド。この資料は DynaText とPDF形式で提供しています。

• ARM ELF specification(SWS ESPC 0003)。PDF形式でinstall_directory\PDF\specs\ARMELF.pdfに収録されています。

• ARM Firmware Suite User Guide(ARM DUI 0136)。この資料はDynaTextと PDF形式で提供しています。

• ARM Firmware Suite Reference Guide(ARM DUI 0102)この資料は DynaTextと PDF形式で提供しています。

• TIS DWARF 2仕様書。PDF形式でinstall_directory\PDF\specs\TIS-DWARF2.pdfに収録されています。

• ARM/Thumb Procedure Call Standard specification(SWS ESPC 0002)。PDF形式でinstall_directory\PDF\specs\ATPCS.pdfに収録されています。

また、ARM製品の関連情報については、以下の出版物を参照して下さい。

• ARM Reference Peripheral Specification(ARM DDI 0062)

• ご使用中のハードウェアデバイスに関する ARMデータシートまたはテクニカルリファレンスマニュアル

Page 11: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

序章

ARM DUI0056DJ-00 Copyright © 1999-2001 ARM Limited. All rights reserved. xi

他の出版物他の出版物他の出版物他の出版物

ARM アーキテクチャに関する一般的な情報については、以下の出版物を参照して下

さい。

• ARM System-on-chip Architecture (second edition), Furber, S., (2000). Addison Wesley. ISBN 0-201-67519-6.

Page 12: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

序章

xii Copyright © 1999-2001 ARM Limited. All rights reserved. ARM DUI0056DJ-00

ご意見・ご質問ご意見・ご質問ご意見・ご質問ご意見・ご質問

ARM Limitedでは、ARMデベロッパスイートおよび本書に関するご意見等をお待ちしています。

ARMデベロッパスイートに関するご意見・ご質問デベロッパスイートに関するご意見・ご質問デベロッパスイートに関するご意見・ご質問デベロッパスイートに関するご意見・ご質問

ADS に関するご意見・ご質問等がございましたら、製品購入元までご連絡下さい。その際、迅速かつ適切な対応をさせて頂くために、以下の情報をご用意下さい。

• ご使用になっている製品のリリース情報

• ハードウェアプラットフォーム、オペレーティングシステムのタイプ、バージョンなど、ご使用になっているプラットフォームについての詳しい情報

• 当該問題が繰り返し発生するコードの小さなスタンドアロンサンプル

• 当初の目的と、実際に起こったことに関する詳しい説明

• コマンドラインオプションを含め、使用した全てのコマンド

• 問題を例示するサンプル出力

• バージョン番号、日付を含め、使用しているツールのバージョン情報

本書に関するご意見本書に関するご意見本書に関するご意見本書に関するご意見

本書に関するご意見等がございましたら、電子メールに以下の情報をご記入の上、

[email protected]までお寄せ下さい。

• 資料名

• 資料番号

• ご意見のあるページ番号

• 問題点の詳しい説明

補足または向上すべき点についてのご提案もお待ちしています。

Page 13: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

ARM DUI0056DJ-00 Copyright © 1999-2001 ARM Limited. All rights reserved. 1-1

第 1章はじめにはじめにはじめにはじめに

本章では ADSデベロッパガイド(本書)について概説します。本章は以下のセクションから構成されています。

• ARMデベロッパガイドについて:P. 1-2

• プログラミングに関する一般事項:P. 1-4

• ARMをターゲットとした開発:P. 1-5

Page 14: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

はじめに

1-2 Copyright © 1999-2001 ARM Limited. All rights reserved. ARM DUI0056DJ-00

1.1 ARMデベロッパガイドについてデベロッパガイドについてデベロッパガイドについてデベロッパガイドについて

本書は、ARM搭載プロセッサ向けのコードを開発する際に役立つ情報が記載されています。全般的に本書の内容は ARMデベロッパスイート(ADS)を使用してコードを開発することを前提としています。

ADSは、支援文書およびサンプルを含み、ARMファミリの RISCプロセッサ用アプリケーションの記述・デバッグを目的としたアプリケーション群で構成されています。ADSを使用することにより、C、C++、ならびに ARMアセンブリ言語プログラムの開発・作成・デバッグが可能となります。

ADSツールキットは、以下の主要コンポーネントから構成されています。

• コマンドライン開発ツール

• GUI開発ツール

• ユーティリティ

• 支援ソフトウェア

ADS付属資料一覧については、P. ix「参考資料」を参照して下さい。

1.1.1 サンプルコードサンプルコードサンプルコードサンプルコード

本書で紹介するサンプルコードの多くは、install_directory\examplesに収録さ

れています。この examples ディレクトリには、本書で紹介していないサンプルコー

ドも含まれています。詳細については、各 example ディレクトリに収録されているreadme.txt を参照して下さい。サンプルコードは以下のディレクトリにインストー

ルされます。

asm ARM アセンブリ言語プログラミングのいくつかのサンプルが収録され

ています。これらのサンプルはADSアセンブラガイドで使用しています。

cpp いくつかの単純な C++サンプルコードが収録されています。また、rwサブディレクトリには Rogue Wave のマニュアルと練習用サンプルが含まれています。

databort 標準データアボートハンドラの設計に関する文書とサンプルコードが収

録されています。

dcc デバッグ通信チャネルの使用方法を示すサンプルコードが収録されてい

ます。このサンプルについては、第 8 章「デバッグ通信チャネル」で説明しています。

dhry Dhrystoneのソースコードが収録されています。

dhryansi Dhrystoneの ANSI Cバージョンが収録されています。

explasm ARM アセンブリ言語プログラミングの補足サンプルが収録されていま

す。

Page 15: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

はじめに

ARM DUI0056DJ-00 Copyright © 1999-2001 ARM Limited. All rights reserved. 1-3

inline Cおよび C++コンパイラのインラインアセンブラの使用方法を示すサンプルが収録されています。これらのサンプルについては、第 4 章「C、C++、アセンブリ言語の混合」で説明しています。

interwork ARM コードと Thumb コード間のインターワーキングの方法を示したサンプルが収録されています。これらのサンプルについては、第 3章「ARMと Thumbのインターワーキング」で説明しています。

mmugen MMUgenユーティリティのソースと文書が収録されています。このユーティリティは、要求される仮想 - 物理アドレス変換を記述した規則ファイルから、MMU ページ可能データを生成することができます(第 7 章「キャッシュと密結合メモリ」参照)。

picpid 位置独立コードの記述方法を示すサンプルが収録されています。詳細に

ついては、このディレクトリにある readme.txtを参照して下さい。

embedded 第 6章「ROMコードの記述」で使用しているソースコードが収録されています。これらのサンプルは、ARM Integrator™ボードをターゲットとし

ています。

sorts ARM C ライブラリに使用される挿入ソート、シェルソート、クイックソートを比較したサンプルコードが収録されています。

swi SWIハンドラのサンプルが収録されています。

Page 16: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

はじめに

1-4 Copyright © 1999-2001 ARM Limited. All rights reserved. ARM DUI0056DJ-00

1.2 プログラミングに関する一般事項プログラミングに関する一般事項プログラミングに関する一般事項プログラミングに関する一般事項

ARM ファミリのプロセッサは RISC プロセッサです。効率的なコードを作成できるプログラミング方式の多くが RISC プロセッサに基づいています。例えば、ARM-Thumbプロシージャコール標準(ATPCS)に準拠した ARMコンパイラは、最初の 4つの整数サイズの関数パラメータをレジスタ r0~ r3に渡します。他のパラメータはスタックに渡されます。つまり、以下のことを意味します。

• 参照により、構造などの大きなパラメータを渡した方が効率的である。

• 可能であれば、関数を 4つ以下の整数サイズのパラメータに限定した方が効率的である。

また、多くの RISC プロセッサと同様に、ARM は境界整列データにアクセスするように設計されています。非整列データへのアクセスは、コードサイズまたはパフォーマンスに影響を及ぼす可能性があります。このようなアクセスからは期待通りの結果が得られない場合もあります。詳細については、http://www.arm.comから ARMによく寄せられる質問とその答えをまとめた FAQリストを参照して下さい。

CISC アーキテクチャから従来のコードを移植する場合には、一般的な RISC プログラミングの方法に慣れておくことを推奨します。

Page 17: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

はじめに

ARM DUI0056DJ-00 Copyright © 1999-2001 ARM Limited. All rights reserved. 1-5

1.3 ARMをターゲットとした開発をターゲットとした開発をターゲットとした開発をターゲットとした開発

本書では、最も一般的な ARMプログラミングタスクについて、サンプルコードを交えながら説明しています。以下のセクションでは各章で取り上げているトピックの内容について概説します。

• プロシージャコール標準の使用

• ARMコードと Thumbコードのインターワーキング

• C、C++、アセンブリ言語の混合:P. 1-6

• プロセッサ例外処理:P. 1-6

• ROMコードの記述:P. 1-7

• キャッシュと密結合メモリ:P. 1-8

• デバッグ通信チャネルの使用:P. 1-8

1.3.1 プロシージャコール標準の使用プロシージャコール標準の使用プロシージャコール標準の使用プロシージャコール標準の使用

ARM-Thumb プロシージャコール標準は、別々にコンパイルし、アセンブルしたモジュールを一緒に機能させる上で守らなければならないレジスタの使用方法とスタックの規則を定義するものです。この基本標準に基づくバリアントはいくつもあります。ARM C/C++ コンパイラは、必ず選択された ATPCS バリアントに準拠するコードを生成します。リンカは必要に応じ、リンクさせるにふさわしい標準 Cまたは C++ライブラリを選択します。

ARM 用のコードを開発する場合には、適切な ATPCS バリアントを選択する必要があります。例えば、ARM状態と Thumb状態間をインターワーキングするコードを記述する場合には、コンパイラとアセンブラで -apcs /interwork オプションを選択する

必要があります。

C または C++ でコードを記述する場合は、コンパイルする全てのモジュールで互換性のある ATPCSオプションを選択していることを確認する必要があります。

自分自身でアセンブリ言語ルーチンを記述する場合には、適切な ATPCSバリアントに準拠していることを確認して下さい。詳細については、第 2 章「プロシージャコール標準の使用」を参照して下さい。

Cとアセンブリ言語を混合する場合には、ATPCSの含意を理解しておく必要があります。

1.3.2 ARMコードとコードとコードとコードと Thumbコードのインターワーキングコードのインターワーキングコードのインターワーキングコードのインターワーキング

Thumb 16ビット命令をサポートするARMプロセッサ向けのコードを記述する場合は、ARM コードと Thumb コードを必要に応じて混合することができます。C または C++でコードを記述する場合は、-atpcs /interworkオプションを使用してコンパイル

を行う必要があります。リンカは、Thumb状態から ARM関数がいつ呼び出され、ARM状態から Thumb関数がいつ呼び出されるのかを検出し、呼び出しと復帰のシーケンスを変更するか、必要に応じてプロセッサ状態を変更するインターワーキングベニアを挿入します。

Page 18: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

はじめに

1-6 Copyright © 1999-2001 ARM Limited. All rights reserved. ARM DUI0056DJ-00

アセンブリ言語ルーチンを記述する場合には、インターワーキング ATPCSバリアントに準拠していることを確認して下さい。ターゲットのアーキテクチャバージョンによって、プロセッサ状態を変更する方法はいくつもあります。詳細については、第 3章「ARMと Thumbのインターワーキング」を参照して下さい。

1.3.3 C、、、、C++、アセンブリ言語の混合、アセンブリ言語の混合、アセンブリ言語の混合、アセンブリ言語の混合

C、C++、ARM アセンブリ言語で記述し、コンパイルとアセンブルを別々に行ったモ

ジュールをプログラムに混在させることができます。C コンパイラおよび C++ コンパイラのインラインアセンブラを使用することにより、C コードまたは C++ コードの中に小さなアセンブリ言語ルーチンを記述できます。しかし、インラインアセンブラを使用する場合には、記述できるアセンブリ言語コードにいくつかの制約があります。この制約については P. 4-2「インラインアセンブラの使用」で説明しています。また、C、C++、アセンブリ言語で記述したモジュール間の呼び出し方法とそのサンプルについては、第 4章「C、C++、アセンブリ言語の混合」を参照して下さい。

1.3.4 プロセッサ例外処理プロセッサ例外処理プロセッサ例外処理プロセッサ例外処理

ARMプロセッサは以下の 7タイプの例外を認識します。

リセットリセットリセットリセット プロセッサリセットピンがアサートされると発生します。この例外は、起動を通知するため、あるいはプロセッサがたった今起動したばかりであるかのようにリセットするためだけに発生することが予想されます。ソフトリセットは、リセットベクタ(0x0000)への分岐によって発生さ

せることができます。

未定義命令未定義命令未定義命令未定義命令 現在実行中の命令が、プロセッサにも接続されているどのコプロセッサにも認識されない場合に発生します。

ソフトウェア割り込み(ソフトウェア割り込み(ソフトウェア割り込み(ソフトウェア割り込み(SWI))))

ユーザ定義の割り込み命令です。ソフトウェア割り込みにより、例えばユーザモードで実行中のプログラムが、RTOS 関数などのスーパバイザモードで実行する特権命令を要求することができます。

プリフェッチアボートプリフェッチアボートプリフェッチアボートプリフェッチアボート

プロセッサが不正アドレスからプリフェッチされた命令を実行しようとしたときに発生します。不正アドレスとは、メモリが存在しないアドレスか、プロセッサが現在のモードでアクセスできないことをメモリ管理サブシステムが決定したアドレスを指します。

データアボートデータアボートデータアボートデータアボート

データ転送命令が不正アドレスでのロードまたはストアを試行したときに発生します。

Page 19: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

はじめに

ARM DUI0056DJ-00 Copyright © 1999-2001 ARM Limited. All rights reserved. 1-7

割り込み(割り込み(割り込み(割り込み(IRQ))))

プロセッサ外部割り込み要求ピンが LOWでアサートされ、かつ IRQ割り込みがイネーブルされているとき(CPSRの Iビットがクリアされているとき)に発生します。

高速割り込み(高速割り込み(高速割り込み(高速割り込み(FIQ))))

プロセッサ外部高速割り込み要求ピンが LOWでアサートされ、かつ FIQ割り込みがイネーブルされているとき(CPSR の F ビットがクリアされているとき)に発生します。この例外は、割り込みレイテンシを最小限に抑える必要があるときに使用するのが一般的です。

通常、例外処理をオペレーティングシステムに頼らない組み込みアプリケーションなどのアプリケーションを記述する場合には、例外タイプごとのハンドラを記述する必要があります。

SWIや IRQ割り込みなど、1つの例外タイプに複数のソースがあるような場合には、各ソースの例外ハンドラをチェインすることができます。詳細については、P. 5-38「例外ハンドラのチェインニング」を参照して下さい。

Thumb対応プロセッサでは、例外が発生するとプロセッサは ARM状態にスイッチします。例外ハンドラを ARM コードで記述することも、ベニアを使用して Thumb 状態にスイッチさせることもできます。詳細については、P. 5-40「Thumb対応プロセッサでの例外処理」を参照して下さい。

1.3.5 ROMコードの記述コードの記述コードの記述コードの記述

ARM ベースのシステム向けに書かれた多くのアプリケーションは、ROM に記憶させ

てリセット時に実行する組み込みアプリケーションです。組み込みオペレーティングシステムを記述する際、あるいはオペレーティングシステムに依存せずにリセットから実行する組み込みアプリケーションを記述する際には、以下を含めていくつか注意しておかねばならない点があります。

• アドレスの再マップ。例えば、アドレス 0にある ROMで初期化し、アドレス 0に RAMを再マップする場合

• 環境とアプリケーションの初期化

• 組み込み実行イメージをリンクし、特定のメモリ位置にコードとデータを配置する。

通常、ARMコアはリセット時にアドレス 0から命令の実行を開始します。したがって組み込みシステムでは、システムをリセットするときに ROMがアドレス 0に存在しなければなりません。しかし、ROM は RAM よりも実行速度が遅く、8 ビット幅または16 ビット幅しかないのが一般的です。このことが例外処理速度に影響を及ぼします。ROMをアドレス 0に配置するということは、例外ベクタを修正できないことを意味します。そこで一般的には、ROM を RAM に再マップし、起動後に例外ベクタを ROMから RAM にコピーする方法を取ります。詳細については、P. 6-4「メモリマップに関する注意点」を参照して下さい。

Page 20: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

はじめに

1-8 Copyright © 1999-2001 ARM Limited. All rights reserved. ARM DUI0056DJ-00

リセット後、組み込みアプリケーションまたはオペレーティングシステムにより、以下のようにシステムを初期化する必要があります。

• 例外ベクタ、スタック、I/Oペリフェラルなどの実行環境を初期化する。

• 非ゼロ書き込み可能データの初期値を書き込み可能データ領域にコピーし、ZIデータ領域をゼロで埋めるなど、アプリケーションを初期化する。

詳細については、P. 6-7「システムの初期化」を参照して下さい。

組み込みシステムは大抵の場合、複雑なメモリコンフィギュレーションを実装しています。例えばある組み込みシステムでは、割り込みハンドラやスタックなどのパフォーマンスを優先するコードに高速 32ビット RAMを使用し、アプリケーション RWデータにはやや速度が落ちる 16ビット RAMを、通常のアプリケーションコードには ROMを使用することが考えられます。リンカの分散ローディング機能を使用すれば、複雑なシステムに適した実行イメージを作成することができます。例えば、分散ロード記述ファイルを使用して、個々のコード領域とデータ領域のロードアドレスと実行アドレスを指定することができます。この方法を示したサンプルと、組み込みアプリケーションに影響を及ぼすセミホスティングなどの他の要素については、第 6章「ROMコードの記述」を参照して下さい。

1.3.6 キャッシュと密結合メモリキャッシュと密結合メモリキャッシュと密結合メモリキャッシュと密結合メモリ

ARM920Tをはじめとする多くの ARMコアでは、キャッシュが CPUと同じチップ上に集積されています。ARM966E-Sなどのいくつかの ARMコアでは、密結合メモリが CPUと同じチップ上に集積されています。

キャッシュと密結合メモリのどちらを使用してもオフチップメモリアクセスを減らせることから、システムのパフォーマンスが向上し、電力消費量を低減させることができます。密結合メモリはキャッシュよりも予測しやすいリアルタイム動作特性をもち、必要となるシリコン面積も小さくて済みます。キャッシュは、アドレス範囲全体にまたがるパフォーマンスの向上に役立ちます。

詳細については、第 7章「キャッシュと密結合メモリ」を参照して下さい。

1.3.7 デバッグ通信チャネルの使用デバッグ通信チャネルの使用デバッグ通信チャネルの使用デバッグ通信チャネルの使用

ARM7TDMI®やARM9TDMI™などのARMコアに組み込まれているEmbeddedICE®ロジッ

クは、デバッグ通信チャネルをサポートしています。これにより、JTAG ポートとMulti-ICE®などのプロトコルコンバータを使用すれば、プログラムフローを停止させた

りデバッグ状態に入ることなく、ターゲットとホストデバッガ間でデータの受け渡しを行うことができます。詳細については、第 8 章「デバッグ通信チャネル」を参照して下さい。

Page 21: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

ARM DUI0056DJ-00 Copyright © 1999-2001 ARM Limited. All rights reserved. 2-1

第 2章プロシージャコール標準の使用プロシージャコール標準の使用プロシージャコール標準の使用プロシージャコール標準の使用

本章では、ARM-Thumbプロシージャコール標準(ATPCS)の使用方法について説明します。別々にコンパイルし、アセンブルしたモジュールを合わせて互いにうまく機能させるには、ATPCS に準拠している必要があります。本章は以下のセクションから構成されています。

• ARM-Thumbプロシージャコール標準について:P. 2-2

• レジスタの役割と名前:P. 2-4

• スタック:P. 2-6

• パラメータの受け渡し:P. 2-9

• 読み出し専用位置独立:P. 2-14

• 読み出し /書き込み位置独立:P. 2-15

• ARM状態と Thumb状態間のインターワーキング:P. 2-16

• 浮動小数点オプション:P. 2-17

Page 22: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

プロシージャコール標準の使用

2-2 Copyright © 1999-2001 ARM Limited. All rights reserved. ARM DUI0056DJ-00

2.1 ARM-Thumbプロシージャコール標準についてプロシージャコール標準についてプロシージャコール標準についてプロシージャコール標準について

ARM-Thumbプロシージャコール標準(ATPCS)に準拠することにより、個々にコンパイルまたはアセンブルしたサブルーチンを相互に機能させることができます。本章では、この ATPCSの使用方法について説明します。

ATPCS にはいくつかのバリアントがあります。本章では、使用するバリアントの選択方法を説明します。

どのバリアントを使用した場合でも、この標準に関する多くの点は共通しています。以下を参照して下さい。

• レジスタの役割と名前:P. 2-4

• スタック:P. 2-6

• パラメータの受け渡し:P. 2-9

2.1.1 ATPCSのバリアントのバリアントのバリアントのバリアント

バリアントとは、基本標準をユーザが個々に選択することのできるオプションによって修正したものです。基本標準に準拠するコードは、他のバリアントに準拠するコードよりも実行速度が速く、占有するメモリ域も小さくて済みます。しかし、基本標準に準拠したコードでは以下を行うことができません。

• ARM状態と Thumb状態間のインターワーキング

• データまたはコードの位置の独立化

• 呼び出しごとの独立データを使用したルーチンへのリエントリ

• スタックチェック

コンパイラまたはアセンブラは、選択されたバリアントを記録する ELF オブジェクトファイル内に属性を設定します。通常は 1 つのバリアントを選択し、一緒に機能させる全てのサブルーチンにこのバリアントを使用する必要があります。この規則の例外については、本文の中で説明しています。

各オプションについては、以下のセクションを参照して下さい。

• スタックリミットチェック:P. 2-11

• 読み出し専用位置独立:P. 2-14

• 読み出し /書き込み位置独立:P. 2-15

• ARM状態と Thumb状態間のインターワーキング:P. 2-16

• 浮動小数点オプション:P. 2-17

2.1.2 ARM Cライブラリライブラリライブラリライブラリ

ARM Cライブラリには、いくつかのバリアントがあります(ADSコンパイラ /ライブラリガイド参照)。オブジェクトファイルとリンクさせるバリアントはリンカが選択します。リンカは、オブジェクトファイル内に記録されている ATPCSオプションと互換性のある最適なバリアントを選択します。詳細については、ADS リンカ / ユーティリティガイドの「リンカ」の章を参照して下さい。

Page 23: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

プロシージャコール標準の使用

ARM DUI0056DJ-00 Copyright © 1999-2001 ARM Limited. All rights reserved. 2-3

2.1.3 ATPCSへの適合性への適合性への適合性への適合性

ADSコンパイラを使用してコンパイルされるルーチンは、選択された ATPCSバリアントに準拠します。

アセンブリ言語で記述したルーチンは、選択した ATPCSバリアントに必ず準拠させる必要があります。

ATPCS に準拠するには、以下の点に注意してアセンブリ言語ルーチンを記述する必要があります。

• 一般に認識されるインタフェースにおいて、この標準で定義されている全ての規則を守っていること

• ATPCSのスタック使用規則を常に守っていること

• -apcsオプションを使用してアセンブルすること

2.1.4 プロセスとメモリモデルプロセスとメモリモデルプロセスとメモリモデルプロセスとメモリモデル

ATPCS は、1 つの実行スレッドまたはプロセスに適用されます。プロセスのメモリ状態は、プロセッサレジスタの内容と、そのプロセスがアドレス指定できるメモリの内容によって定義されます。

プロセスは、以下のいくつか、または全てのタイプのメモリをアドレス指定することができます。

• 読み出し専用メモリ

• 静的に割り当てられる読み出し -書き込みメモリ

• 動的に割り当てられる読み出し -書き込みメモリ。このメモリはヒープメモリと呼ばれます。

• スタックメモリ。P. 2-6「スタック」参照

2つのプロセスが相互機能するように特別に設計していない限りは、1つのプロセスで別のプロセスのメモリ状態を変更してはなりません。

Page 24: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

プロシージャコール標準の使用

2-4 Copyright © 1999-2001 ARM Limited. All rights reserved. ARM DUI0056DJ-00

2.2 レジスタの役割と名前レジスタの役割と名前レジスタの役割と名前レジスタの役割と名前

ATPCSでは、目的ごとに使用するレジスタが決められています。

2.2.1 レジスタの役割レジスタの役割レジスタの役割レジスタの役割

以下のレジスタの使用方法は、別途記載していない限り、ATPCS の全てのバリアントに適用されます。ATPCSに準拠するには、以下の規則を守る必要があります。

• パラメータ値をルーチンに渡し、結果値を受け取るレジスタには、レジスタ r0~r3を使用します。この使用方法を明確にするために、r0~ r3を a1~ a4として参照することができます。詳細については、P. 2-9「パラメータの受け渡し」を参照して下さい。サブルーチンコール間では、どのような目的にも r0~ r3を使用することができます。呼び出されるルーチンは、復帰する前に r0~ r3を復元する必要はありません。呼び出し元のルーチンが r0~ r3の内容を後で必要とする場合は、そのルーチンで r0~ r3の内容を保存する必要があります。

• ルーチンのローカル変数の値を保持するレジスタには、レジスタ r4~ r11を使用します。この使用方法を明確にするために、r4~ r11を v1~ v8として参照することができます。Thumb状態の場合はほとんどの命令で、ローカル変数にはレジスタ r4~ r7しか使用できません。

呼び出されるルーチンがこれらのレジスタを使用する場合は、そのルーチンが復帰前にこれらのレジスタの値を復元する必要があります。

• レジスタ r12 は、コール内スクラッチレジスタ、ip です。この役割では、r12 はインターワーキングベニアなどのプロシージャリンケージベニアで使用されます。プロシージャコール間では、r12 はどのような目的にも使用することができます。呼び出されるルーチンは、復帰前に r12を復元する必要はありません。

• レジスタ r13は、スタックポインタ、spです。このレジスタを他の目的で使用してはなりません。呼び出されるルーチンからのイグジットで sp に保持される値は、そのエントリで保持される値と同じでなければなりません。

• レジスタ r14は、リンクレジスタ、lrです。復帰アドレスを保存する場合は、r14をコール間の他の目的に使用することができます。

• レジスタ r15は、プログラムカウンタ、pcです。このレジスタを他の目的に使用することはできません。

Page 25: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

プロシージャコール標準の使用

ARM DUI0056DJ-00 Copyright © 1999-2001 ARM Limited. All rights reserved. 2-5

2.2.2 レジスタの名前レジスタの名前レジスタの名前レジスタの名前

表 2-1は、定義されているプロセッサレジスタの役割と、それぞれに関連付けられている名前を示しています。これらの名前と、それぞれの同義語は、アセンブラで事前定義されています。アセンブラ言語を生成するとき、コンパイラはこの表が示す特殊名と基本レジスタ名を使用します。

また、s0~ s31、d0~ d15、f0~ f31は、浮動小数点コプロセッサのレジスタ用に事前定義されている名前です。詳細については、P. 2-18「VFP アーキテクチャ」およびP. 2-20「FPAアーキテクチャ」を参照して下さい。

表表表表 2-1 ATPCSで定義されているレジスタの役割と名前で定義されているレジスタの役割と名前で定義されているレジスタの役割と名前で定義されているレジスタの役割と名前

レジスタレジスタレジスタレジスタ 同義語同義語同義語同義語 特殊特殊特殊特殊 プロシージャコール標準における役割プロシージャコール標準における役割プロシージャコール標準における役割プロシージャコール標準における役割

r15 - pc プログラムカウンタ

r14 - lr リンクレジスタ

r13 - sp スタックポインタ

r12 - ip プロシージャコール内スクラッチレジスタ

r11 v8 - ARM状態変数レジスタ 8

r10 v7 sl ARM状態変数レジスタ 7。スタックチェック対象バリアント内のスタックリミットポインタ

r9 v6 sb ARM 状態変数レジスタ 6。RWPI バリアントのスタティックベース

r8 v5 - ARM状態変数レジスタ 5

r7 v4 - 変数レジスタ 4

r6 v3 - 変数レジスタ 3

r5 v2 - 変数レジスタ 2

r4 v1 - 変数レジスタ 1

r3 a4 - 引数 /結果 /スクラッチレジスタ 4

r2 a3 - 引数 /結果 /スクラッチレジスタ 3

r1 a2 - 引数 /結果 /スクラッチレジスタ 2

r0 a1 - 引数 /結果 /スクラッチレジスタ 1

Page 26: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

プロシージャコール標準の使用

2-6 Copyright © 1999-2001 ARM Limited. All rights reserved. ARM DUI0056DJ-00

2.3 スタックスタックスタックスタック

このセクションでは、基本標準におけるスタックの使用方法を説明します。詳細については、P. 2-11「スタックリミットチェック」を参照して下さい。

ATPCSでは以下が定義されています。

• フル下降スタック

• 全ての外部インタフェースにおける 8バイトスタックアライメント

2.3.1 スタック関連用語スタック関連用語スタック関連用語スタック関連用語

ATPCSでは以下のスタック関連用語を使用しています。

スタックポインタスタックポインタスタックポインタスタックポインタ

スタックに最後に書き込まれる(プッシュされる)アドレス

スタックベーススタックベーススタックベーススタックベース

スタックの最上位アドレス。スタックは上から下に向かって展開されます。スタックが実際に使用する最上位の位置は、スタックベースよりも下で最初に出現するワードの位置です。

スタックリミットスタックリミットスタックリミットスタックリミット

スタックの中で現在のプロセスが使用することを許される最下位アドレスです。

使用済みスタック使用済みスタック使用済みスタック使用済みスタック

スタックベースとスタックポインタ間のメモリ領域です。この領域にスタックポインタは含まれますが、スタックベースは含まれません。

未使用スタック未使用スタック未使用スタック未使用スタック

スタックポインタとスタックリミット間のメモリ領域です。この領域にスタックリミットは含まれますが、スタックポインタは含まれません。

スタックフレームスタックフレームスタックフレームスタックフレーム レジスタを保存し、ローカル変数を保持する目的で、ルーチンによってスタックに割り当てられるメモリ領域

プロセスがスタックベースとスタックリミットの現在の値にアクセスできる場合と、そうでない場合があります。

割り込みハンドラは、割り込むプロセスのスタックを使用することができます。この場合、プログラマはスタックリミットを超えないように注意する必要があります。

Page 27: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

プロシージャコール標準の使用

ARM DUI0056DJ-00 Copyright © 1999-2001 ARM Limited. All rights reserved. 2-7

図図図図 2-1 スタックメモリのレイアウトスタックメモリのレイアウトスタックメモリのレイアウトスタックメモリのレイアウト

2.3.2 スタックの展開スタックの展開スタックの展開スタックの展開

-g コマンドラインオプションを使用したコンパイルによって生成されるオブジェクトファイルには、DWARF2 デバッグフレーム情報が含まれています。デバッガはデバッグ時に必要であれば、この情報を使用してスタックを展開します。これにより、デバッガでスタックのバックトレースを表示させることができます。

アセンブリ言語では、FRAME ディレクティブを使用してスタックフレームを記述する

必要があります。アセンブラはこれらのスタックフレームを使用して、DWARF2デバッグフレーム情報を生成します。詳細については、ADSアセンブラガイドの「ARM/Thumbアセンブリ言語の記述」および「ディレクティブについて」を参照して下さい。

Page 28: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

プロシージャコール標準の使用

2-8 Copyright © 1999-2001 ARM Limited. All rights reserved. ARM DUI0056DJ-00

2.3.3 8バイトアライメントバイトアライメントバイトアライメントバイトアライメント

システムによっては、多重転送を行う場合に 8 バイトアライメントのアドレスを使用することによって、メモリアクセス速度を上げることができます。ARMv5TEプロセッサで LDRD命令と STRD命令を使用する場合には、8バイトアライメントを設定する必要があります。

コンパイラが生成するオブジェクトファイルは、全ての外部インタフェースにおいてスタックを 8 バイトアライメントで維持します。コンパイラはビルド属性を設定することで、これをリンカに通知します。

アセンブリ言語で ATPCSに準拠するには、オブジェクトファイルに外部呼び出しが含まれていない場合を除き、以下を守る必要があります。

• 全ての外部インタフェースにおいて、スタックの 8バイトアライメントを維持すること(スタックポインタは、コードへのエントリと、コードからの外部呼び出しとの間で、必ず偶数ワードずつ移動する必要があります。)

• PRESERVE8 ディレクティブを使用して、8 バイトアライメントが維持されていることをリンカに通知すること(ADSアセンブラガイドの「ディレクティブについて」を参照)

Page 29: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

プロシージャコール標準の使用

ARM DUI0056DJ-00 Copyright © 1999-2001 ARM Limited. All rights reserved. 2-9

2.4 パラメータの受け渡しパラメータの受け渡しパラメータの受け渡しパラメータの受け渡し

使用する引数の数が一定でないルーチンを可変ルーチンと呼びます。一定数の引数を使用するルーチンを不変ルーチンと呼びます。可変ルーチンと不変ルーチンでは、パラメータの受け渡しに適用される規則が異なります。

このセクションでは、この規則に関する基本標準について説明します。浮動小数点オプションの関連情報については、P. 2-17「浮動小数点オプション」を参照して下さい。

2.4.1 不変ルーチン不変ルーチン不変ルーチン不変ルーチン

不変ルーチンには、パラメータ値が以下のように渡されます。

1. 最初の整数引数が r0~ r3に順に割り当てられる(「ロング整数の割り当て」参照)。

2. 残りのパラメータが順にスタックに割り当てられる(「ロング整数の割り当て」参照)。

警告警告警告警告

スタックへのアクセスは、コードサイズと実行速度に影響を及ぼします。パラ

メータの数はできる限り 5個未満に抑えて下さい。

ロング整数の割り当てロング整数の割り当てロング整数の割り当てロング整数の割り当て

long longのように、32ビットを超える整数パラメータの場合には、一部がレジスタに、一部がスタックに割り当てられることがあります。この場合、スタックに割り当てられる部分は、パラメータリスト内の順序に沿っていなくても、どの FP値よりも先に割り当てられます。

浮動小数点数の割り当て浮動小数点数の割り当て浮動小数点数の割り当て浮動小数点数の割り当て

システムに浮動小数点ハードウェアがある場合には、以下のように FPパラメータが FPレジスタに割り当てられます。

1. 各 FPパラメータが順番に検査される。

2. パラメータごとに、使用可能な FPレジスタセットが検査される。

3. 使用可能な FP レジスタセットが検出された場合、パラメータを保持できるだけの大きさを持つ、最小番号の付いた連続する FP レジスタセットがそのパラメータに割り当てられる。

Page 30: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

プロシージャコール標準の使用

2-10 Copyright © 1999-2001 ARM Limited. All rights reserved. ARM DUI0056DJ-00

2.4.2 可変ルーチン可変ルーチン可変ルーチン可変ルーチン

可変ルーチンの場合、パラメータはレジスタ a1~ a4に渡され、必要に応じてスタックが使用されます(a1~ a4は、r0~ r3の同義語です)。

使用されるワード順序は、あたかもパラメータ値が連続するメモリワードにストアされた後で以下に転送されるかのような順序となります。

1. a1から順に、a1~ a4

2. スタックの最下位アドレスから順に(つまり、パラメータ値は逆の順序でスタックにプッシュされることになります。)

注注注注

この結果、浮動小数点値は場合によって整数レジスタだけに渡されるか、スタックだけに渡されるか、あるいは整数レジスタとスタックに分割して渡されます。

2.4.3 結果のリターン結果のリターン結果のリターン結果のリターン

関数は以下を返すことができます。

• 1ワードの整数値を a1に

• 2~ 4ワードの整数値を a1~ a2、a1~ a3、あるいは a1~ a4に

• 浮動小数点値を f0、d0、あるいは s0に

• 複合浮動小数点値(complexなど)を f0~ fNまたは d0~ dNに。Nの最大値は、選択する浮動小数点アーキテクチャによって異なります(P. 2-17「浮動小数点オプション」参照)。

• 上記のどれよりも長い値は、メモリ内に間接的に返す必要があります。

Page 31: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

プロシージャコール標準の使用

ARM DUI0056DJ-00 Copyright © 1999-2001 ARM Limited. All rights reserved. 2-11

2.5 スタックリミットチェックスタックリミットチェックスタックリミットチェックスタックリミットチェック

プログラムに必要となる最大容量のスタックメモリを設計ステージで正確に計算できる場合を除いては、ソフトウェアスタックリミットチェック(/swst)オプションを

選択して下さい。

ソフトウェアスタックリミットチェック無効(/noswst)オプションは、プログラム

に必要となる最大容量のスタックメモリを設計ステージで正確に計算できる場合だけに選択して下さい。デフォルトではこの設定が使用されます。

スタックリミットチェックを考慮しなくてもいいような方法でアセンブリコードを記述することも可能です。ファイル内のコードがスタックリミットチェックを必要としない場合でも、/swst または /noswst を使用してアセンブルされる他のコードとの

互換性を維持しなければならない場合があります。この場合は、ソフトウェアスタックリミットチェック非該当(/swstna)オプションを使用して下さい。

2.5.1 スタックリミットチェック対象コードに適用される規則スタックリミットチェック対象コードに適用される規則スタックリミットチェック対象コードに適用される規則スタックリミットチェック対象コードに適用される規則

スタックリミットチェックを行うATPCSのバリアントでは、以下の規則が適用されます。

• slが、スタック内で一番下の使用可能なアドレスの少なくとも 256バイト上を指していなければならない。

注注注注

割り込みハンドラがユーザモードスタックを使用できる場合には、slとスタック内の使用可能な最下位アドレスとの間に、この 256バイトに加えて十分な空間を見ておく必要があります。

• slが、スタックリミットチェックを選択してコンパイルまたはアセンブルされるコードによって変更されることがあってはならない(slは、ランタイムサポートコードによって変更されます)。

• spに保持されている値は、必ず slの値以上でなければならない。

2.5.2 スタックリミットチェックを行うときのレジスタの使用方法スタックリミットチェックを行うときのレジスタの使用方法スタックリミットチェックを行うときのレジスタの使用方法スタックリミットチェックを行うときのレジスタの使用方法

スタックチェックオプションを選択してアセンブルまたはコンパイルするルーチンでは、r10を変更することも、これを復元することもできません。レジスタ r10は、スタックリミットポインタ、slです。

他の全ての場合におけるレジスタの使用方法は、スタックリミットチェックを行う場合もそうでない場合も同じです(P. 2-4「レジスタの役割と名前」参照)。

2.5.3 Cおよびおよびおよびおよび C++でのスタックチェックでのスタックチェックでのスタックチェックでのスタックチェック

ソフトウェアスタックリミットチェック(/swst)オプションを選択すると、コンパ

イラはスタックチェックを実行するオブジェクトコードを生成します。

Page 32: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

プロシージャコール標準の使用

2-12 Copyright © 1999-2001 ARM Limited. All rights reserved. ARM DUI0056DJ-00

2.5.4 アセンブリ言語でのスタックチェックアセンブリ言語でのスタックチェックアセンブリ言語でのスタックチェックアセンブリ言語でのスタックチェック

アセンブリコードに対してソフトウェアスタックチェック(/swst)オプションを指

定する場合には、スタックチェックを実行するコードを自分自身で記述する必要があります。

リーフルーチンとは、他のサブルーチンを呼び出さないルーチンを意味します。

リーフルーチンについては、以下の 3つのケースを考慮しておく必要があります。

• 256バイト未満のスタックを使用するリーフルーチン

• 256バイト未満のスタックを使用する非リーフルーチン

• 256バイトを超えるスタックを使用するルーチン:P. 2-13

この目的では、リーフルーチンはルーチン内のどの呼び出しも末端呼び出しとなるルーチンで構成します。

256バイト未満のスタックを使用するリーフルーチンバイト未満のスタックを使用するリーフルーチンバイト未満のスタックを使用するリーフルーチンバイト未満のスタックを使用するリーフルーチン

256 バイト未満のスタックしか使用しないリーフルーチンでは、スタックリミットをチェックする必要はありません。これは前述の規則によるものです(P. 2-11「スタックリミットチェック対象コードに適用される規則」参照)。

この目的では、リーフルーチンは総スタック使用量が 256 バイト未満のルーチンの組み合わせで構成することができます。

256バイト未満のスタックを使用する非リーフルーチンバイト未満のスタックを使用する非リーフルーチンバイト未満のスタックを使用する非リーフルーチンバイト未満のスタックを使用する非リーフルーチン

256 バイト未満のスタックを使用する非リーフルーチンには、以下のようなリミットチェックシーケンスを使用することができます。

SUB sp, sp, #size ; ARM code version CMP sp, sl BLLO __ARM_stack_overflow

または、Thumbコードの場合:

ADD sp, #-size ; Thumb code version CMP sp, sl BLLO __Thumb_stack_overflow

注注注注

__ARM_stack_overflowおよび__Thumb_stack_overflowは単なる例示的な名前であり、実際の実装に対応しているわけではありません。

Page 33: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

プロシージャコール標準の使用

ARM DUI0056DJ-00 Copyright © 1999-2001 ARM Limited. All rights reserved. 2-13

256バイトを超えるスタックを使用するルーチンバイトを超えるスタックを使用するルーチンバイトを超えるスタックを使用するルーチンバイトを超えるスタックを使用するルーチン

この場合は以下のようなシーケンスを使用して、sp の新しい値をリミットチェックを行うコードに提示する必要があります。

SUB ip, sp, #size ; ARM code version CMP ip, sl BLLO __ARM_stack_overflow

または、Thumbコードの場合:

LDR r7, #-size ; Thumb code version ADD r7, sp CMP r7, sl BLLO __Thumb_stack_overflow

spがスタック内の使用可能な最下位アドレスを下回ることがないようにするためには、このように spの値を提示する必要があります。

注注注注

__ARM_stack_overflowおよび__Thumb_stack_overflowは単なる例示的な名前であり、実際の実装に対応しているわけではありません。

Page 34: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

プロシージャコール標準の使用

2-14 Copyright © 1999-2001 ARM Limited. All rights reserved. ARM DUI0056DJ-00

2.6 読み出し専用位置独立読み出し専用位置独立読み出し専用位置独立読み出し専用位置独立

プログラムの全ての読み出し専用セグメントが位置独立セグメントであるとき、そのプログラムは読み出し専用位置独立(ROPI)型となります。

ROPIセグメントは位置独立コード(PIC)であることが多いものの、読み出し専用データであることもあれば、PICと読み出し専用データの組み合わせであることもあります。

コードを特定のメモリ位置にロードしなくても済むようにするには、ROPIオプションを選択して下さい。このオプションは、以下のようなルーチンに特に効果的です。

• ランタイムイベントに対応してロードされるルーチン

• 状況によって他のルーチンとの様々な組み合わせでメモリにロードされるルーチン

• 実行中に別のアドレスにマップされるルーチン

2.6.1 ROPIに関するレジスタの使用方法に関するレジスタの使用方法に関するレジスタの使用方法に関するレジスタの使用方法

ROPIの有無に関係なく、レジスタの使用方法は同じです(P. 2-4「レジスタの役割と名前」参照)。

2.6.2 ROPIコードの記述コードの記述コードの記述コードの記述

ROPIのコードを記述する場合:

• ROPI セグメント内のコードから、同一 ROPI セグメント内のシンボルへの参照は、pc 相対にする必要があります。ATPCS では、読み出し専用セグメント用の他のベースレジスタは定義されていません。ROPI セグメント内のアドレスは、ROPIセグメントにストアすることはできません。

• ROPI セグメント内のコードから、異なる ROPI セグメント内のシンボルへの参照は、pc相対にする必要があります。2つのセグメントは、互いに一定して相対となるようにする必要があります。

• ROPI セグメントからの他のどの参照も、以下のどちらかを指している必要があります。

— 絶対アドレス

— 書き込み可能データへの sb相対参照(P. 2-15「読み出し /書き込み位置独立」参照)

• ROPIセグメント内のシンボルをアドレス指定する読み出し -書き込みワードは、その ROPIセグメントが移動するたびに調整する必要があります。

Page 35: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

プロシージャコール標準の使用

ARM DUI0056DJ-00 Copyright © 1999-2001 ARM Limited. All rights reserved. 2-15

2.7 読み出し読み出し読み出し読み出し /書き込み位置独立書き込み位置独立書き込み位置独立書き込み位置独立

プログラムの全ての読み出し -書き込みセグメントが位置独立セグメントであるとき、そのプログラムは読み出し -書き込み位置独立(RWPI)型となります。

RWPIセグメントは通常、位置独立データ(PID)です。

RWPIオプションを選択すれば、データの特定のメモリ位置を決める必要がなくなります。この方法は、リエントラントルーチンで何度もインスタンス生成しなければならないデータに使用すると、特に効果的です。

2.7.1 リエントラントルーチンリエントラントルーチンリエントラントルーチンリエントラントルーチン

リエントラントルーチンは、同時に複数のプロセスでスレッド化することができます。各プロセスには、リエントラントルーチンの読み出し -書き込みセグメントのコピーをもたせます。各コピーは、それぞれスタティックベースレジスタの異なる値でアドレス指定されます。

2.7.2 RWPIに関するレジスタの使用方法に関するレジスタの使用方法に関するレジスタの使用方法に関するレジスタの使用方法

レジスタ r9 は、スタティックベース、sb です。このレジスタは、外部に認識可能なルーチンが呼び出されるときに、常に適切なスタティックデータセグメントのベースアドレスを指している必要があります。

sbを使用しないルーチンでは、r9を他の目的に使用することもできます。この場合は、sb の内容をルーチンへのエントリで保存し、イグジットの前に復元する必要があります。また、sb の内容は、外部ルーチンへの呼び出しが発生する前に復元する必要があります。

他の全ての場合におけるレジスタの使用方法は、RWPIを使用する場合もそうでない場合も同じです(P. 2-4「レジスタの役割と名前」参照)。

2.7.3 位置独立データのアドレシング位置独立データのアドレシング位置独立データのアドレシング位置独立データのアドレシング

RWPIセグメントは、それが初めて使用されるまでに再配置することができます。RWPIセグメント内のシンボルのアドレスは、以下のように計算されます。

1. リンカが、セグメント内の固定位置からの読み出し専用オフセットを計算する。規則に基づき、この固定位置は、プログラムの中で最下位アドレスが指定されたRWPIセグメントの先頭バイトの位置となります。

2. ランタイムで、この読み出し専用オフセットを、スタティックベースレジスタ sbの内容に加算するオフセットとして使用する。

2.7.4 アセンブリ言語を使用したアセンブリ言語を使用したアセンブリ言語を使用したアセンブリ言語を使用した RWPIの記述の記述の記述の記述

読み出し専用セグメントから RWPI セグメントへの参照は、sb の値に固定(読み出し専用)オフセットを加算して計算します(ADS アセンブラガイド「ディレクティブについて」の「DCDO」を参照)。

Page 36: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

プロシージャコール標準の使用

2-16 Copyright © 1999-2001 ARM Limited. All rights reserved. ARM DUI0056DJ-00

2.8 ARM状態と状態と状態と状態と Thumb状態間のインターワーキング状態間のインターワーキング状態間のインターワーキング状態間のインターワーキング

以下の状況下でコードをコンパイルまたはアセンブルする場合は、/interwork オプ

ションを選択して下さい。

• Thumb状態の読み出し元に復帰できる ARMルーチン

• ARM状態の読み出し元に復帰できる Thumbルーチン

• ARMから Thumbへ、または Thumbから ARMへの呼び出しで、状態と切り替えるコードをリンカに生成させたいとき

以下の状況下でコードをコンパイルまたはアセンブルする場合は、/nointerworkオ

プションを選択して下さい。

• システムで Thumbを使用しないとき

• 全ての状態変更を処理するアセンブラコードを記述するとき

デフォルトは以下のとおりです。

• /interwork:ARM v5T プロセッサ向けのコードをコンパイルまたはアセンブルする場合

• /nointerwork:上記以外の場合

インターワーキングオプションを選択すると、使用される命令セットを考慮しなくても、異なるモジュール内のルーチンを呼び出すことができます。必要であれば、リンカはインターワーキングコールベニアを挿入するか、コールサイトをパッチします。この処理は、コンパイルまたはアセンブルされたコードに作用します。

詳細については、第 3章「ARMと Thumbのインターワーキング」を参照して下さい。

2.8.1 インターワーキングに関するレジスタの使用方法インターワーキングに関するレジスタの使用方法インターワーキングに関するレジスタの使用方法インターワーキングに関するレジスタの使用方法

インターワーキングの有無に関係なく、レジスタの使用方法は同じです(P. 2-4「レジスタの役割と名前」参照)。

Page 37: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

プロシージャコール標準の使用

ARM DUI0056DJ-00 Copyright © 1999-2001 ARM Limited. All rights reserved. 2-17

2.9 浮動小数点オプション浮動小数点オプション浮動小数点オプション浮動小数点オプション

ATPCSは、2つの異なる浮動小数点ハードウェアアーキテクチャと命令セットをサポートしています。

• VFPアーキテクチャ(P. 2-18「VFPアーキテクチャ」参照)

• FPAアーキテクチャ(P. 2-20「FPAアーキテクチャ」参照)。このアーキテクチャは、下位互換性を維持する目的だけでサポートされています。

一方のアーキテクチャに準拠したコードは、他方のアーキテクチャでは使用できません。

ADS に含まれているコンパイラとアセンブラには、6 つの浮動小数点オプションが用意されています。

• -fpu VFP

• -fpu FPA

• -fpu softVFP

• -fpu softVFP+VFP

• -fpu softFPA

• -fpu none

ターゲットシステムに浮動小数点ハードウェアが存在する場合には、VFP、

softVFP+VFP、FPAのいずれかを選択して下さい。

システムに浮動小数点ハードウェアが存在し、Thumb コードから浮動小数点ライブラリルーチンを使用したい場合には、softVFP+VFPを選択して下さい。

ターゲットシステムに浮動小数点ハードウェアが存在しない場合:

• FPA システムとの互換性を維持する必要があるとき、あるいは SDT で作成したオブジェクトを使用するときは、softFPAを選択して下さい。

• コンパイルまたはアセンブルするモジュールが浮動小数点演算を行わず、かつFPA システムと VFP システムの両方との互換性を維持する必要があるときは、noneを選択して下さい。

• その他の場合には、softVFP を選択して下さい。デフォルトではこの設定が使

用されます。

P. 2-21「浮動小数点ハードウェアが不在の場合」を参照して下さい。

Page 38: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

プロシージャコール標準の使用

2-18 Copyright © 1999-2001 ARM Limited. All rights reserved. ARM DUI0056DJ-00

2.9.1 VFPアーキテクチャアーキテクチャアーキテクチャアーキテクチャ

VFPアーキテクチャでは、16個の倍精度レジスタ、d0~ d15を使用します。各倍精度レジスタは、2つの単精度レジスタとして使用することができます。単精度レジスタとしては、これらのレジスタは s0~ s31として参照されます。例えば、d5は、s10と s11を足したものと同じことです。

VFPアーキテクチャは拡張精度をサポートしていません。

ベクタモードとスカラモードベクタモードとスカラモードベクタモードとスカラモードベクタモードとスカラモード

VFPアーキテクチャには、以下の 2つの演算モードがあります。

• スカラモード

• ベクタモード

ATPCSは、スカラモード演算だけに適用されます。ATPCSに準拠した、全てに認識されるルーチンへのエントリ、またはそのルーチンからのイグジットにおけるベクタ長とベクタストライドには、1を設定する必要があります。

VFPに関するレジスタの使用方法に関するレジスタの使用方法に関するレジスタの使用方法に関するレジスタの使用方法

先頭 8個の倍精度レジスタ、d0~ d7を以下の目的に使用することができます。

• 浮動小数点値をルーチンに渡す。

• ルーチンから浮動小数点値を渡す。

• ルーチン内のスクラッチレジスタとして

各倍精度レジスタは、1つの倍精度値か 2つの単精度値を保持することができます。浮動小数点引数値は、それぞれの値を順番に適切なタイプの空きレジスタに割り当てながら、浮動小数点レジスタに割り当てられます。

例えば、以下の値を渡す場合:

1.0(倍)2.0(倍)3.0(倍)4.0(倍)5.0(単)6.0(単)

パラメータ値は以下のようにレジスタに割り当てられます。

Page 39: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

プロシージャコール標準の使用

ARM DUI0056DJ-00 Copyright © 1999-2001 ARM Limited. All rights reserved. 2-19

ATPCSに準拠するには、ルーチン内でレジスタ d8~ d15を使用する場合に、これらの値をエントリで保存し、イグジットの前に復元する必要があります。これらのレジスタの内容は、1つの FSTMX命令で保存することができ、1つの FLDMX命令で復元する

ことができます。これらの内容は、単精度値または倍精度値として解釈されるのではなく、ビットパタンとして保存・復元されます。N個の単精度値の保存には、N+1ワードが使用されます。

VFP値の形式値の形式値の形式値の形式

単精度値および倍精度値は、IEEE 754 標準形式に準拠します。倍精度値は、真の 64ビット値として処理されます。

• リトルエンディアンモードでは、指数を含め、2ワードを使用する倍精度値の上位ワードに、上位アドレスが割り当てられます。

• ビッグエンディアンモードでは、上位ワードに下位アドレスが割り当てられます。

注注注注

VFP におけるリトルエンディアンの倍精度値には、純リトルエンディアン形式が適用されます。この点は、FPAアーキテクチャと異なります。

ビッグエンディアンの倍精度値には、VFPと FPAのどちらのアーキテクチャでも、純ビッグエンディアン形式が使用されます。

IEEEに準拠した丸めモードと例外イネーブルフラグに準拠した丸めモードと例外イネーブルフラグに準拠した丸めモードと例外イネーブルフラグに準拠した丸めモードと例外イネーブルフラグ

ATPCS では、これに準拠したルーチンへのエントリ、またはルーチンからのイグジットにおける状態に関する制約条件を設けていません。

Page 40: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

プロシージャコール標準の使用

2-20 Copyright © 1999-2001 ARM Limited. All rights reserved. ARM DUI0056DJ-00

2.9.2 FPAアーキテクチャアーキテクチャアーキテクチャアーキテクチャ

FPA アーキテクチャでは、8 個の浮動小数点レジスタ、f0 ~ f7 が使用されます。各レジスタは、1つの単精度値、倍精度値、拡張精度値のいずれかを保持することができます。

FPAに関するレジスタの使用方法に関するレジスタの使用方法に関するレジスタの使用方法に関するレジスタの使用方法

最初の 4個の浮動小数点レジスタ、f0~ f3を以下に使用することができます。

• 浮動小数点値をルーチンに渡す。

• ルーチンから浮動小数点結果を渡す。

• ルーチン内のスクラッチレジスタとして

ATPCSに準拠するには、ルーチン内で浮動小数点レジスタ f4~ f7を使用する場合に、これらの値をエントリで保存し、イグジットの前に復元する必要があります。これらのレジスタの内容は、1 つの SFM 命令で保存することができ、1 つの LFM 命令で復元

することができます。各値の保存に 3ワードが使用されます。

FPA値の形式値の形式値の形式値の形式

単精度値および倍精度値は、IEEE 754 標準形式に準拠します。指数を含め、浮動小数点値の最上位ワードには、最下位メモリアドレスが割り当てられます。この規則は、ワード内のバイト順序がビッグエンディアンであってもリトルエンディアンであっても変わりません。

注注注注

リトルエンディアンの倍精度値は、純リトルエンディアン形式でも純ビッグエンディアン形式でもありません。

IEEEに準拠した丸めモードと例外イネーブルフラグに準拠した丸めモードと例外イネーブルフラグに準拠した丸めモードと例外イネーブルフラグに準拠した丸めモードと例外イネーブルフラグ

ATPCS では、これに準拠したルーチンへのエントリ、またはルーチンからのイグジットにおける状態に関する制約条件を設けていません。

Page 41: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

プロシージャコール標準の使用

ARM DUI0056DJ-00 Copyright © 1999-2001 ARM Limited. All rights reserved. 2-21

2.9.3 浮動小数点ハードウェアが不在の場合浮動小数点ハードウェアが不在の場合浮動小数点ハードウェアが不在の場合浮動小数点ハードウェアが不在の場合

softVFPと softFPAの違いは、リトルエンディアンモードにおける倍精度値のワード順序だけです(P. 2-19「VFP値の形式」および P. 2-20「FPA値の形式」参照)。

-fpu noneを指定する場合は、浮動小数点値を使用できません。

softVFPとととと softFPAに関するレジスタの使用方法に関するレジスタの使用方法に関するレジスタの使用方法に関するレジスタの使用方法

各浮動小数点引数は、メモリにストアするときのように、1つまたは 2つの整数ワード内のビットパタンに変換されます。この結果得られる整数値は、P. 2-9「パラメータの受け渡し」で説明した方法で渡されます。

単精度の浮動小数点結果は、ビットパタンで r0に返されます。

倍精度の浮動小数点結果は、r0と r1に返されます。r0は、メモリ内の値を表現した最下位アドレスのワードに対応するワードを保持します。

2.9.4 softVFP+VFP

Thumb にはコプロセッサ命令がないため、Thumb コードが浮動小数点値を浮動小数点レジスタに渡すことはできません。

VFP コプロセッサが存在し、Thumb コードから浮動小数点ルーチンを使用したい場合には、-fpu softVFP+VFPオプションを選択して下さい。

このオプションは、-fpu softVFPを指定したときと同じパラメータ受け渡し規則を

使用してコードを生成するようにコンパイラに指示します。Cライブラリの浮動小数点ルーチンは、ARM状態から VFP命令を使用します。

Page 42: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

プロシージャコール標準の使用

2-22 Copyright © 1999-2001 ARM Limited. All rights reserved. ARM DUI0056DJ-00

Page 43: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

ARM DUI0056DJ-00 Copyright © 1999-2001 ARM Limited. All rights reserved. 3-1

第 3章ARMとととと Thumbのインターワーキングのインターワーキングのインターワーキングのインターワーキング

本章では、Thumb命令セット実装プロセッサ向けのコードを記述する際の、ARM状態と Thumb状態の切り替え方法について説明します。本章は以下のセクションから構成されています。

• インターワーキングについて:P. 3-2

• アセンブリ言語のインターワーキング:P. 3-6

• Cと C++のインターワーキングおよびベニア:P. 3-11

• ベニアを使用したアセンブリ言語のインターワーキング:P. 3-15

Page 44: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

ARMと Thumbのインターワーキング

3-2 Copyright © 1999-2001 ARM Limited. All rights reserved. ARM DUI0056DJ-00

3.1 インターワーキングについてインターワーキングについてインターワーキングについてインターワーキングについて

ARM コードと Thumb コードは自由に混在させることができますが、そのコードはARM/Thumb プロシージャコール標準の要件に準拠していなければなりません。ARMコンパイラは、必ずこの標準に準拠したコードを生成します。ARMアセンブリ言語モジュールを記述する場合は、記述するコードをこの標準に準拠させる必要があります。

ARMリンカは、ARM関数がいつ Thumb状態から呼び出され、Thumb関数がいつ ARM状態から呼び出されるのかを検出します。ARMリンカは必要に応じ、呼び出し -復帰命令を変更するか、ベニアと呼ばれる小さなコードセクションを挿入することによって、プロセッサ状態を切り替えます。

ARMアーキテクチャ v5Tでは、特別な命令を使用しなくてもプロセッサ状態を変更することができます。通常、ARMアーキテクチャ v5Tプロセッサではインターワーキングを行うことによる影響はありません。

複数のソースファイルをリンクさせる場合は、全てのファイルで互換性のある ATPCSオプションを使用している必要があります。互換性のないオプションが検出されると、リンカはエラーメッセージを生成します。

Page 45: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

ARMと Thumbのインターワーキング

ARM DUI0056DJ-00 Copyright © 1999-2001 ARM Limited. All rights reserved. 3-3

3.1.1 インターワーキングに適した状況インターワーキングに適した状況インターワーキングに適した状況インターワーキングに適した状況

Thumb対応 ARMプロセッサ向けのコードを記述するとき、恐らくはアプリケーションのほとんどを Thumb状態で実行するように記述するでしょう。この方法を使用すれば、コード密度を最大限に向上させることができます。さらに、8 ビット幅または 16 ビット幅のメモリを使用する場合には、これによって最高のパフォーマンスを得ることができます。しかし、以下のような理由で、アプリケーションの一部を ARM状態で実行したい場合も考えられます。

速度速度速度速度 アプリケーションは、部分的にとにかく速度を優先しなければならない場合があります。このようなセクションは、Thumb 状態よりも ARM 状態で実行した方が効率的かもしれません。状況によっては、1つの ARM命令で、等価な Thumb命令を使用するよりも多くのことを行える場合があります。

例えば、小容量の高速 32ビットメモリを実装しているシステムがあるとします。このメモリから ARM コードを実行すれば、8 ビットまたは 16ビットのメモリから各メモリをフェッチするオーバヘッドを発生させずに済みます。

機能機能機能機能 Thumb 命令は、等価な ARM 命令に比べると柔軟性の点で劣ります。動作によっては Thumb状態では実行できないものもあります。例えば、割り込みやコプロセッサへのアクセスをイネーブル / ディセーブルすることはできません。これらの動作を実行するには、状態を切り替える必要があります。

例外処理例外処理例外処理例外処理 プロセッサ例外が発生すると、プロセッサは自動的に ARM 状態に入り

ます。つまり、たとえ例外ハンドラが後で Thumb状態にリエントリして例外のメイン処理を実行する場合でも、この例外ハンドラの最初の部分は ARM 命令でコーディングする必要があります。このような処理の終

わりでハンドラからメインアプリケーションに戻るには、プロセッサはARM状態に戻る必要があります。

スタンドアロンのスタンドアロンのスタンドアロンのスタンドアロンの Thumbプログラムプログラムプログラムプログラム

Thumb 対応 ARM プロセッサは、必ず ARM 状態で起動します。デバッガの下で単純な Thumb アセンブリ言語プログラムを実行するには、Thumb状態への状態変更を実行するARMヘッダを追加し、メインThumbルーチンを呼び出す必要があります。このサンプルについては、P. 3-8「ARMヘッダのサンプル」を参照して下さい。

Page 46: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

ARMと Thumbのインターワーキング

3-4 Copyright © 1999-2001 ARM Limited. All rights reserved. ARM DUI0056DJ-00

3.1.2 /interworkオプションの使用オプションの使用オプションの使用オプションの使用

-apcs /interworkオプションは、全てのコンパイラとアセンブラに使用できます。

このオプションを設定した場合:

• コンパイラまたはアセンブラが、インターワーキング属性をオブジェクトファイル内に記録します。

• リンカがサブルーチンエントリにインターワーキングベニアを挿入します。

• アセンブリ言語では、呼び出し元の命令セット状態に復帰する BX LR などの関

数イグジットコードを記述する必要があります。

• Cまたは C++では、コンパイラが呼び出し元の命令セット状態に復帰する関数イグジットコードを生成します。

• Cまたは C++では、コンパイラは間接呼び出しまたは仮想呼び出しに BX命令を

使用します。

オブジェクトファイルに以下が含まれている場合は、/interwork オプションを使用

して下さい。

• ARMコードに復帰する必要があるかもしれない Thumbサブルーチン

• Thumbコードに復帰する必要があるかもしれない ARMサブルーチン

• ARMコードへの間接呼び出しまたは仮想呼び出しを行う可能性のある Thumbサブルーチン

• Thumbコードへの間接呼び出しまたは仮想呼び出しを行う可能性のあるARMサブルーチン

上記が含まれていなければ、/interwork オプションを使用する必要はありません。

例えば、オブジェクトファイルは /interworkを必要としない以下のコードで構成す

ることができます。

• 例外による割り込みが可能な Thumbコード。この例外がプロセッサを ARM状態に切り替えるため、ベニアは必要ありません。

• Thumbコードから例外を処理することができる例外処理コード。このコードの復帰にはベニアは必要ありません。

• 他のファイルに含まれている ARMサブルーチンを呼び出す Thumbコード(このインターワーキングの復帰シーケンスは、呼び出し元ではなく、呼び出し先に従属します)

• 他のファイルに含まれている Thumbサブルーチンを呼び出す ARMコード(このインターワーキングの復帰シーケンスは、呼び出し元ではなく、呼び出し先に従属します)

Page 47: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

ARMと Thumbのインターワーキング

ARM DUI0056DJ-00 Copyright © 1999-2001 ARM Limited. All rights reserved. 3-5

3.1.3 インターワーキングコールの検出インターワーキングコールの検出インターワーキングコールの検出インターワーキングコールの検出

リンカは、呼び出されるルーチンがインターワーキング用にビルドされていない直接ARM/Thumbインターワーキングコールを検出すると、エラーを生成します。この場合は、呼び出されるルーチンをインターワーキング用に再ビルドする必要があります。

例えば、例 3-1は、-apcs /interworkオプションを指定せずに P. 3-12例 3-3の ARM

ルーチンをコンパイルしたときに生成されるエラーを示しています。

例例例例 3-1

Error: L6239E: Cannot call ARM symbol 'arm_function' in non-interworking objectarmsub.o from THUMB code in thumbmain.o(.text)

このようなタイプのエラーは、ARMから Thumbへの、または Thumbから ARMへのインターワーキングコールが、そのルーチンのシンボルとは異なるオブジェクトモジュールから検出されたにも関わらず、呼び出されるルーチンがインターワーキング用にコンパイルされていないことを示します。この場合は、このシンボルを含むモジュールを、-apcs /interworkを指定して再コンパイルする必要があります。

Page 48: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

ARMと Thumbのインターワーキング

3-6 Copyright © 1999-2001 ARM Limited. All rights reserved. ARM DUI0056DJ-00

3.2 アセンブリ言語のインターワーキングアセンブリ言語のインターワーキングアセンブリ言語のインターワーキングアセンブリ言語のインターワーキング

アセンブリ言語ソースファイルには、複数のエリア(ELF セクションに対応するエリア)を含めることができます。各エリアは、ARM命令と Thumb命令の一方または両方を保持することができます。

リンカを使用して、呼び出し元とは異なる命令セットを使用するルーチンとの間の呼び出しを設定できます。この場合は、BL を使用してルーチンを呼び出します(P. 3-15

「ベニアを使用したアセンブリ言語のインターワーキング」参照)。

必要であれば、命令セットを明示的に変更するコードを記述することも可能です。状況によっては、こうすることでサイズの小さい、速いコードを記述することが可能です。

プロセッサ状態の切り替えを行う命令は以下のとおりです。

• BX:P. 3-7「分岐交換命令」参照

• BLX、LDR、LDM、POP(ARMアーキテクチャ v5以上のみ):P. 3-10「ARMアーキテクチャ v5T」参照

以下のディレクティブは、適切な命令セットから命令をアセンブルするようにアセンブラに指示します(P. 3-8「アセンブラモードの変更」参照)。

• CODE16

• CODE32

Page 49: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

ARMと Thumbのインターワーキング

ARM DUI0056DJ-00 Copyright © 1999-2001 ARM Limited. All rights reserved. 3-7

3.2.1 分岐交換命令分岐交換命令分岐交換命令分岐交換命令

BX命令は、指定されたレジスタに含まれるアドレスに分岐します。この分岐アドレス

のビット 0の値により、ARM状態と Thumb状態のどちらで実行を継続するかが決定されます。ARMアーキテクチャv5で使用可能な他の命令については、P. 3-10「ARMアーキテクチャ v5T」を参照して下さい。

アドレスのビット 0をこの方法で使用できるのは、以下の理由によります。

• 全ての ARM命令がワード境界で整列するため、どの ARM命令でもアドレスのビット 0とビット 1は使用されない。

• 全ての Thumb命令がハーフワード境界で整列するため、どの Thumb命令でもアドレスのビット 0は使用されない。

構文構文構文構文

BX命令の構文には以下のどちらかを使用します。

Thumb BX Rn

ARM BX{cond} Rn

各オプションの説明:

Rn

r0 ~ r15 の中で、分岐先のアドレスを保持するレジスタを指定します。このレジスタのビット 0 の値によって、プロセッサ状態が以下のように決定されます。

• ビット 0 がセットされている場合は、分岐アドレスにある命令がThumb状態で実行されます。

• ビット 0 がクリアされている場合は、分岐アドレスにある命令がARM状態で実行されます。

cond オプションの条件コードを指定します。条件付きで実行できるのは ARM

バージョンの BXだけです。

Page 50: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

ARMと Thumbのインターワーキング

3-8 Copyright © 1999-2001 ARM Limited. All rights reserved. ARM DUI0056DJ-00

3.2.2 アセンブラモードの変更アセンブラモードの変更アセンブラモードの変更アセンブラモードの変更

ARMアセンブラは、Thumbコードと ARMコードの両方をアセンブルできます。-16オプションで呼び出されない限り、アセンブラはデフォルトで ARMコードをアセンブルします。

どの Thumb対応 ARMプロセッサも ARM状態で起動するため、Thumb状態への分岐・交換を行うには BX命令を使用する必要があり、その後に CODE16ディレクティブを使

用して Thumb命令をアセンブルするようにアセンブラに指示する必要があります。アセンブラに ARM命令のアセンブルに戻るように指示するには、このディレクティブに対応する CODE32ディレクティブを使用します。

これらのディレクティブの詳細については、ADSアセンブラガイドを参照して下さい。

3.2.3 ARMヘッダのサンプルヘッダのサンプルヘッダのサンプルヘッダのサンプル

P. 3-9 例 3-2 には、4 つのコードセクションが含まれています。最初のセクションは、プロセッサを Thumb 状態に変更する ARM コードの短いヘッダセクションを実装しています。

このヘッダコードは以下を使用しています。

• 分岐アドレスをロードし、最下位ビットを設定する ADR擬似命令。ADR擬似命令は、r0に pc+offset+1の値をロードすることによって、このアドレスを生成します。ADR擬似命令の詳細については、ADSアセンブラガイドを参照して下さい。

• Thumbコードに分岐し、プロセッサ状態を変更する BX命令

ThumbProgというラベルの付いた、このモジュールの 2番目のセクションの前には、以後のコードを Thumbコードとして処理するようにアセンブラに指示する CODE16が配

置されています。この Thumbコードは 2つのレジスタの内容を加算します。

プロセッサを ARM 状態に戻しています。このコードは再度 ADR 命令を使用してラベ

ルのアドレスを取得しますが、このときの最下位ビットはクリアされたままです。次の BX命令で状態が変更されます。

3番目のコードセクションでは、単純に 2つのレジスタの内容を加算しています。

stopとラベルの付いた最後のセクションでは、通常のアプリケーションの終了を通知

するセミホスティング SWI を使用しています。セミホスティングの詳細については、ADSデバッグターゲットガイドを参照して下さい。

注注注注

Thumbセミホスティング SWIの数値は、ARMセミホスティング SWIと異なります(0x123456ではなく 0xAB)。

Page 51: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

ARMと Thumbのインターワーキング

ARM DUI0056DJ-00 Copyright © 1999-2001 ARM Limited. All rights reserved. 3-9

例例例例 3-2

AREA AddReg,CODE,READONLY ; Name this block of code. ENTRY ; Mark first instruction to call.main ADR r0, ThumbProg + 1 ; Generate branch target address ; and set bit 0, hence arrive ; at target in Thumb state. BX r0 ; Branch exchange to ThumbProg.

CODE16 ; Subsequent instructions are Thumb code.ThumbProg MOV r2, #2 ; Load r2 with value 2. MOV r3, #3 ; Load r3 with value 3. ADD r2, r2, r3 ; r2 = r2 + r3 ADR r0, ARMProg BX r0 CODE32 ; Subsequent instructions are ARM code.ARMProg MOV r4, #4 MOV r5, #5 ADD r4, r4, r5

stop MOV r0, #0x18 ; angel_SWIreason_ReportException LDR r1, =0x20026 ; ADP_Stopped_ApplicationExit SWI 0x123456 ; ARM semihosting SWI

END ; Mark end of this file.

サンプルのビルドサンプルのビルドサンプルのビルドサンプルのビルド

上記のサンプルをビルドし、実行するには:

1. テキストエディタを使用してコードを入力し、addreg.sというファイル名で保存します。

2. コマンドプロンプトの後に armasm -g addreg.s と入力し、このソースファイルをアセンブルします。

3. armlink addreg.o -o addregと入力し、このファイルをリンクさせます。

4. armsd addreg と入力し、このモジュールをコマンドラインデバッガにロードします。

5. step を入力し、残りのプログラムを 1 度に 1 命令ずつステップ実行します。1命令の実行が終わるごとに reg を入力し、レジスタを表示させます。プロセッサが Thumb 状態に入ることを確認します。プロセッサが Thumb 状態に入ると、カレントプログラムステータスレジスタ(CPSR)内の T が小文字から大文字のTに変更されます。

Page 52: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

ARMと Thumbのインターワーキング

3-10 Copyright © 1999-2001 ARM Limited. All rights reserved. ARM DUI0056DJ-00

3.2.4 ARMアーキテクチャアーキテクチャアーキテクチャアーキテクチャ v5T

ARMアーキテクチャ v5以上の場合:

• BXの他に、インターワーキングに使用できる 2つの命令があります。

BLX address

プロセッサはリンクを使用して addressへの pc相対分岐を実行し、状態を変更します。address は、ARM コードでは pcの 32MB以内、Thumbコードでは pcの 4MB以内に配置する必要があります。

BLX register

プロセッサは、指定されたレジスタに保持されているアドレスへのリンク付き分岐を実行します。ビット 0の値によって、次のプロセッサ状態が決定されます。

次の状態がどちらであっても、lrのビット [0] には CPSR内の Thumb ビットの現在値がセットされます。したがって、復帰命令は自動的に正しいプロセッサ状態に戻ることができます。

• LDR、LDMあるいは POPが pcへのロードを行うとき、これらの命令は CPSRのThumbビットに、pcにロードされた値のビット [0]をセットします。この原理を利用して命令セットを変更することができます。サブルーチンからの復帰にはこの方法が特に効果的です。同じ復帰命令で、ARMと Thumbのどちらの呼び出し元にも戻ることができます。

詳細については、ADSアセンブラガイドおよび ARM Architecture Reference Manualを参照して下さい。

3.2.5 Thumbコード内のラベルコード内のラベルコード内のラベルコード内のラベル

リンカは以下を参照するラベルを区別します。

• ARM命令

• Thumb命令

• データ

リンカは、Thumb 命令を参照するラベルの値を再配置するときに、再配置する値の最下位ビットをセットします。したがってラベルへの分岐が発生すると、自動的に適切な命令セットが選択されます。この操作は、以下のいずれかの命令が分岐に使用されているときに行われます。

• ARMアーキテクチャ v4Tでは BXを使用した場合

• アーキテクチャ v5T以上では、BX、BLX、LDRを使用した場合

ADSおよび SDTの旧バージョンでは、Thumbコード内のデータは DATAディレクティ

ブでマーキングする必要がありました。現在はこの必要がありません。

Page 53: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

ARMと Thumbのインターワーキング

ARM DUI0056DJ-00 Copyright © 1999-2001 ARM Limited. All rights reserved. 3-11

3.3 Cとととと C++のインターワーキングおよびベニアのインターワーキングおよびベニアのインターワーキングおよびベニアのインターワーキングおよびベニア

ARM用と Thumb用にコンパイルする Cコードと C++コードは自由に混在させることができますが、ARM アーキテクチャ v4T で状態の変更を行うには、ARM コードと

Thumb コードの間にベニアと呼ばれる小さなコードセグメントが必要となります。ARMリンカは、インターワーキングコールを検出すると、これらのインターワーキングベニアを生成します。

3.3.1 インターワーキングさせるコードのコンパイルインターワーキングさせるコードのコンパイルインターワーキングさせるコードのコンパイルインターワーキングさせるコードのコンパイル

-apcs /interworkコンパイラオプションを指定することで、ARMと Thumbの全ての C/C++ コンパイラが、一方のプロセッサ状態に合わせてコンパイルされるルーチンで呼び出せるルーチンを含むモジュールをコンパイルできるようになります。

tcc -apcs /interworkarmcc -apcs /interworktcpp -apcs /interworkarmcpp -apcs /interwork

ARMアーキテクチャv4Tでインターワーキング用にコンパイルされるモジュールから生成されるコードは、一般的に Thumbで 2%、ARMで 1%と若干コードサイズが大きくなります。ARMアーキテクチャ v5では違いはありません。

本体に関数呼び出しが含まれないリーフ関数の場合、コンパイラによって生成されるコードに見られる唯一の違いは、MOV pc,lrが BX lrに置き換えられる点です。MOV

命令では、状態変更を発生させることができません。

ARMアーキテクチャv4T向けにビルドされた非リーフ関数では、Thumbコンパイラは、例えば以下のような 1つの命令を

POP {r4,r5,pc}

以下のようなシーケンスに置き換える必要があります。

POP {r4,r5} POP {r3} BX r3

これによってパフォーマンスに多少の影響が生じます。ソースモジュールは、インターワーキングに使用しないことが確実である場合を除き、全てのソースモジュールをインターワーキング用にコンパイルして下さい。

-apcs /interworkオプションを使用しても、モジュールのコンパイルによって生成

されるコードエリアのインターワーキング属性が設定されます。リンカはこの属性を検出し、適切なベニアを挿入します。

Page 54: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

ARMと Thumbのインターワーキング

3-12 Copyright © 1999-2001 ARM Limited. All rights reserved. ARM DUI0056DJ-00

注注注注

インターワーキング用にコンパイルされた ARMコードは、ARMアーキテクチャ v4T、または v5 以上でしか使用できません。これは他のプロセッサは BX 命令を実装しないためです。

ベニアに使用される容量を確認したい場合は、armlink -info veneersオプションを使用して下さい。

Cを使用したインターワーキングのサンプルを使用したインターワーキングのサンプルを使用したインターワーキングのサンプルを使用したインターワーキングのサンプル

例 3-3は、ARMサブルーチンへのインターワーキングコールを実行する Thumbルーチンを示しています。このARMサブルーチンコールは、Thumbライブラリ内のprintf()

へのインターワーキングコールを発生させます。and armsub.c.これらの 2つのモジュールは、Examples\Interworkディレクトリの thumbmain.cと armsub.cに収録さ

れています。

例例例例 3-3

/********************** * thumbmain.c * **********************/ #include <stdio.h> extern void arm_function(void); int main(void) { printf("Hello from Thumb World\n"); arm_function(); printf("And goodbye from Thumb World\n"); return (0); }

/********************** * armsub.c * **********************/ #include <stdio.h> void arm_function(void) { printf("Hello and Goodbye from ARM world\n"); }

これらのモジュールをコンパイルし、リンクさせるには:

1. システムプロンプトに続けて tcc -c -apcs /interwork -o thumbmain.othumbmain.cを入力し、この Thumbコードをインターワーキング用としてコンパイルします。

2. armcc -c -apcs /interwork -o armsub.o armsub.c を入力し、このARMコードをインターワーキング用としてコンパイルします。

Page 55: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

ARMと Thumbのインターワーキング

ARM DUI0056DJ-00 Copyright © 1999-2001 ARM Limited. All rights reserved. 3-13

3. armlink -o hello armsub.o thumbmain.oを入力し、これらのオブジェクトファイルをリンクさせます。

また、armlink -info veneers armsub.o thumbmain.oを入力すると、イ

ンターワーキングベニアのサイズを表示させることができます(例 3-4)。

例例例例 3-4

Adding veneers to the image

Adding AT veneer (12 bytes) for call to '_printf' from armsub.o(.text). Adding TA veneer (12 bytes) for call to 'arm_function' from thumbmain.o(.text). Adding AT veneer (12 bytes) for call to '__rt_lib_init' from kernel.o(x$codeseg). Adding AT veneer (12 bytes) for call to '__rt_lib_shutdown' from kernel.o(x$codeseg). Adding AT veneer (12 bytes) for call to '_sys_exit' from kernel.o(x$codeseg). Adding AT veneer (12 bytes) for call to '__raise' from rt_raise.o(x$codeseg). Adding AT veneer (12 bytes) for call to '_no_fp_display' from printf2.o(x$codeseg).

7 Veneer(s) (total 84 bytes) added to the image.

Page 56: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

ARMと Thumbのインターワーキング

3-14 Copyright © 1999-2001 ARM Limited. All rights reserved. ARM DUI0056DJ-00

3.3.2 インターワーキングの原則インターワーキングの原則インターワーキングの原則インターワーキングの原則

アプリケーション内のインターワーキングには以下の規則が適用されます。

• 他方の命令セットに戻る可能性のある関数を含む C または C++ モジュールをコンパイルするときは、-apcs /interworkコマンドラインオプションを使用しなければならない。

• 他方の命令セットの関数を呼び出す可能性のある間接または仮想関数呼び出しを含む Cまたは C++モジュールをコンパイルするときは、-apcs /interworkコマンドラインオプションを使用しなければならない。

• 関数ポインタを使用した呼び出しなどの間接呼び出しを、他方の状態にあるコードから非インターワーキングコードに対して行ってはならない。

• 入力オブジェクトに Thumbコードが含まれていれば、リンカは Thumbランタイムライブラリを選択する。これらのライブラリはインターワーキング用にビルドされています。

リンカコマンドラインで、ユーザライブラリの1つを明示的に指定する場合には、それが適切なインターワーキングライブラリであることを確認する必要があります。

3.3.3 同一関数の同一関数の同一関数の同一関数の 2つのコピーの使用つのコピーの使用つのコピーの使用つのコピーの使用

2つの関数に同じ名前を付け、一方を ARMコードとして、他方を Thumbコードとしてコンパイルすることができます。しかし、この方法は推奨できません。ほとんど全ての場合において、同一関数を 1 つしか使用しない場合と比べても、パフォーマンスはほとんど向上しません。

注注注注

関数の 2つのバージョンは、Thumbバージョンが必ず Thumb状態から、ARMバージョンが必ず ARM 状態から呼び出されるとは限らないため、/interwork オプションを使用してコンパイルする必要があります。

一方の定義が Thumbルーチンを定義し、他方が ARMルーチンを定義している限り、リンカは重複する定義を検出してもこれを容認します。

Page 57: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

ARMと Thumbのインターワーキング

ARM DUI0056DJ-00 Copyright © 1999-2001 ARM Limited. All rights reserved. 3-15

3.4 ベニアを使用したアセンブリ言語のインターワーキングベニアを使用したアセンブリ言語のインターワーキングベニアを使用したアセンブリ言語のインターワーキングベニアを使用したアセンブリ言語のインターワーキング

P. 3-6「アセンブリ言語のインターワーキング」で説明した、アセンブリ言語によるARM/Thumbインターワーキング方式では、必要な全ての中間処理を実行しました。このときはリンカがインターワーキングベニアを挿入する必要はありませんでした。

このセクションでは、以下の目的でのインターワーキングベニアの使用方法を説明します。

• アセンブリ言語モジュール間のインターワーキング

• アセンブリ言語モジュールと、Cまたは C++モジュール間のインターワーキング

3.4.1 ベニアを使用したアセンブリ言語だけのインターワーキングベニアを使用したアセンブリ言語だけのインターワーキングベニアを使用したアセンブリ言語だけのインターワーキングベニアを使用したアセンブリ言語だけのインターワーキング

リンカによって生成されるインターワーキングベニアを利用するアセンブリ言語ARM/Thumbインターワーキングコードを記述することができます。このためには以下を記述する必要があります。

• 非インターワーキングルーチンと同じように、BL 命令を使用して呼び出しを行う呼び出し元ルーチン。呼び出し元ルーチンは、/interworkまたは/nointerworkでアセンブルすることができます。

• BX命令を使用して復帰する呼び出し先ルーチン。呼び出し先ルーチンは、/interworkでアセンブルする必要があります。

一般的にこの作業は ARMアーキテクチャv4Tだけで必要とされます。この作業を行わないと、呼び出し元と呼び出し先が離れすぎたり、異なるエリアに配置される可能性があります。ARMアーキテクチャ v5Tでは、呼び出し元と呼び出し先が十分に近ければ、ベニアは必要ありません。

Page 58: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

ARMと Thumbのインターワーキング

3-16 Copyright © 1999-2001 ARM Limited. All rights reserved. ARM DUI0056DJ-00

ベニアを使用したアセンブリ言語のインターワーキングのサンプルベニアを使用したアセンブリ言語のインターワーキングのサンプルベニアを使用したアセンブリ言語のインターワーキングのサンプルベニアを使用したアセンブリ言語のインターワーキングのサンプル

例 3-5は、レジスタ r0~ r2に、値 1、2、3をそれぞれセットするコードを示しています。レジスタ r0 と r2は ARMコードによってセットされます。r1は Thumbコードによってセットされます。以下の点に注意して下さい。

• このコードは-apcs /interworkオプションを指定してアセンブルする必要が

あります。

• サブルーチンからの復帰には、通常の MOV pc,lrではなく、BX lr命令が使用

されています。

例例例例 3-5

; ***** ; arm.s ; ***** AREA Arm,CODE,READONLY ; Name this block of code. IMPORT ThumbProg ENTRY ; Mark 1st instruction to call.ARMProg MOV r0,#1 ; Set r0 to show in ARM code. BL ThumbProg ; Call Thumb subroutine. MOV r2,#3 ; Set r2 to show returned to ARM. ; Terminate execution. MOV r0, #0x18 ; angel_SWIreason_ReportException LDR r1, =0x20026 ; ADP_Stopped_ApplicationExit SWI 0x123456 ; ARM semihosting SWI END

; ******* ; thumb.s ; ******* AREA Thumb,CODE,READONLY ; Name this block of code. CODE16 ; Subsequent instructions are Thumb. EXPORT ThumbProgThumbProg MOV r1, #2 ; Set r1 to show reached Thumb code. BX lr ; Return to ARM subroutine. END ; Mark end of this file.

以下のステップに従ってこのモジュールのビルドとリンクを行い、インターワーキングベニアを確認して下さい。

1. armasm arm.sを入力して ARMコードをアセンブルします。

2. armasm -16 -apcs /interwork thumb.sを入力して Thumbコードをアセンブルします。

3. armlink arm.o thumb.o -o countを入力し、この 2つのオブジェクトファイルをリンクさせます。

Page 59: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

ARMと Thumbのインターワーキング

ARM DUI0056DJ-00 Copyright © 1999-2001 ARM Limited. All rights reserved. 3-17

4. armsd countと入力して、このコードをデバッガにロードします。

5. armsdコマンドプロンプトに続けて list 0x8000と入力し、コードをリスト出力します。例 3-6はこの出力を示しています。

例例例例 3-6

armsd: list 0x8000ARMProg 0x00008000: 0xe3a00001 .... : > mov r0,#1 0x00008004: 0xeb000005 .... : bl $Ven$AT$$ThumbProg 0x00008008: 0xe3a02003 . .. : mov r2,#3 0x0000800c: 0xe3a00018 .... : mov r0,#0x18 0x00008010: 0xe59f1000 .... : ldr r1,0x00008018 ; = #0x00020026 0x00008014: 0xef123456 V4.. : swi 0x123456 0x00008018: 0x00020026 &... : dcd 0x00020026 &...ThumbProg+0000 0x0000801c: 0x2102 .! : mov r1,#2+0002 0x0000801e: 0x4770 pG : bx r14$Ven$AT$$ThumbProg+0000 0x00008020: 0xe59fc000 .... : ldr r12,0x00008028 ; = #0x0000801d+0004 0x00008024: 0xe12fff1c ../. : bx r12+0008 0x00008028: 0x0000801d .... : dcd 0x0000801d ....+000c 0x0000802c: 0xe800e800 .... : dcd 0xe800e800 ....+0010 0x00008030: 0xe7ff0010 .... : dcd 0xe7ff0010 ....+0014 0x00008034: 0xe800e800 .... : dcd 0xe800e800 ....+0018 0x00008038: 0xe7ff0010 .... : dcd 0xe7ff0010 ....

これを見ると、リンカが必要な ARM-Thumbインターワーキングベニアを追加したことが分かります。このベニアは 0x8020~ 0x8028の位置に挿入されていま

す。0x8028には、ビット 0がセットされた、分岐交換先のルーチンのアドレス0x801Dが配置されています。

3.4.2 ベニアを使用したベニアを使用したベニアを使用したベニアを使用した C、、、、C++、アセンブリ言語のインターワーキング、アセンブリ言語のインターワーキング、アセンブリ言語のインターワーキング、アセンブリ言語のインターワーキング

ある状態で実行するようにコンパイルされた Cおよび C++コードは、他方の状態で実行するように設計されたアセンブリ言語コードを呼び出すことが可能であり、またこの逆も可能です。このようなインターワーキングを行うには、非インターワーキングルーチンのように呼び出し元ルーチンを記述し、アセンブリ言語からの呼び出しである場合には、BL命令を使用してこの呼び出しを行います(P. 3-18例 3-7参照)。この次の手順は以下のとおりです。

• 呼び出し先ルーチンが Cで記述されている場合は、-apcs /interworkを使用してこれをコンパイルします。

• 呼び出し先ルーチンがアセンブリ言語で記述されている場合は、-apcs /interworkオプションを使用してこれをアセンブルし、BX lrを使用して復帰します。

Page 60: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

ARMと Thumbのインターワーキング

3-18 Copyright © 1999-2001 ARM Limited. All rights reserved. ARM DUI0056DJ-00

注注注注

この方法で使用するアセンブリ言語コードまたはユーザライブラリは、適宜 ATPCSに準拠させる必要があります。

例例例例 3-7

/********************** * thumb.c * **********************/ #include <stdio.h> extern int arm_function(int); int main(void) { int i = 1; printf("i = %d\n", i); printf("And now i = %d\n", arm_function(i)); return (0); }

; ***** ; arm.s ; ***** AREA Arm,CODE,READONLY ; Name this block of code. EXPORT arm_functionarm_function ADD r0,r0,#4 ; Add 4 to first parameter. BX LR ; Return END

以下のステップに従って、これらのモジュールのビルドとリンクを行って下さい。

1. tcc -c -apcs /interwork thumb.cを入力して Thumbコードをアセンブルします。

2. armasm -apcs /interwork arm.sを入力して ARMコードをアセンブルします。

3. armlink arm.o thumb.o -o addを入力し、この 2つのオブジェクトファイルをリンクさせます。

4. armsd addを入力し、このコードをロードします。

5. goを入力し、コードを実行します。

6. main 関数として生成されたコードをリスト表示させるには、list main と入力します。

7. 生成されたコードをリスト表示させるには、list arm_functionと入力します。

Page 61: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

ARM DUI0056DJ-00 Copyright © 1999-2001 ARM Limited. All rights reserved. 4-1

第 4章C、、、、C++、アセンブリ言語の混合、アセンブリ言語の混合、アセンブリ言語の混合、アセンブリ言語の混合

本章では、C、C++、ARM アセンブリ言語の混合コードの記述方法と、C および C++からの ARMインラインアセンブラの使用方法について説明します。本章は以下のセクションから構成されています。

• インラインアセンブラの使用:P. 4-2

• アセンブリコードから Cグローバル変数へのアクセス:P. 4-15

• C++からの Cヘッダファイルの使用:P. 4-16

• C、C++、アセンブリ言語間の呼び出し:P. 4-18

Page 62: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

C、C++、アセンブリ言語の混合

4-2 Copyright © 1999-2001 ARM Limited. All rights reserved. ARM DUI0056DJ-00

4.1 インラインアセンブラの使用インラインアセンブラの使用インラインアセンブラの使用インラインアセンブラの使用

Cコンパイラと C++コンパイラに内蔵されているインラインアセンブラを使用して、Cから直接アクセスできないターゲットプロセッサの以下のような機能を使用することができます。

• 飽和演算(ADSアセンブラガイド参照)

• コプロセッサの使用

• PSR

インラインアセンブラは、CおよびC++との非常に柔軟なインターワーキングをサポートしています。どのレジスタオペランドにも、任意の C式または C++式を使用することができます。また、インラインアセンブラは複雑な命令を展開し、アセンブリ言語コードを最適化します。

注注注注

デフォルトで、あるいはコンパイラオプションの -O1または -O2で最適化がイネーブルされている場合、インラインアセンブリ言語はコンパイラが行う最適化の対象となります。

armccおよび armcppの 2つのインラインアセンブラは、汎用コプロセッサ命令、ハーフワード命令、ロング乗算を含む ARM 命令セットのほとんどを実装しています。tccと tcpp の 2 つのインラインアセンブラは、2つの例外を除き、Thumb 命令セットを全て実装しています。

注注注注

tcc と tcpp は廃止予定のインラインアセンブラであり、今後の ADS バージョンではサポートされません。

制約条件の詳細については、P. 4-7「インラインアセンブラと armasm との違い」を参照して下さい。

インラインアセンブラは高水準アセンブラです。インラインアセンブラが生成するコードは、ユーザが記述するコードと全く同じであるとは限りません。インラインアセンブラは、コンパイラが生成するコードよりも効率的なコードを生成するという目的では使用しないで下さい。この目的では、ARMアセンブラarmasmを使用して下さい。

pcへの書き込みによる分岐など、ARMアセンブラ armasmで使用できるいくつかの低レベル機能はサポートされていません。

4.1.1 インラインアセンブラの呼び出しインラインアセンブラの呼び出しインラインアセンブラの呼び出しインラインアセンブラの呼び出し

ARM Cコンパイラは、__asm指定子が使用されていれば、インラインアセンブリ言語をサポートします。

ARM C++コンパイラは、ANSI C++標準規格で提示されている asm構文をサポートし

ていますが、ストリングリテラルは 1 ストリングでなければならないという制約があります。例:

asm("instruction[;instruction]");

Page 63: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

C、C++、アセンブリ言語の混合

ARM DUI0056DJ-00 Copyright © 1999-2001 ARM Limited. All rights reserved. 4-3

この asm構文は、Cと C++を両方コンパイルするときに、C++コンパイラにサポートされます。asmステートメントは、C関数内または C++関数内に配置する必要があります。ストリングリテラルにコメントを含めてはなりません。asmステートメントは、

Cまたは C++ステートメントが予想される場所であればどこにでも使用できます。

asm構文に加え、ARM C++は Cコンパイラの __asm構文をサポートしています。

インラインアセンブラは、アセンブラ指定子を使用して呼び出します。この指定子に続けて、ブレース({ })で囲んだアセンブラ命令のリストを指定します。例:

__asm{ instruction [; instruction] ... [instruction]}

2つの命令を同一行に指定する場合は、セミコロンで区切る必要があります。1つの命令が複数行にまたがる場合は、行の継続を示す逆スラッシュ文字(\)を使用する必要

があります。C または C++ で記述したコメントは、インラインアセンブリ言語ブロック内のどこにでも挿入することができます。

ストリングコピーのサンプルストリングコピーのサンプルストリングコピーのサンプルストリングコピーのサンプル

例4-1は、ストリングコピールーチンにおけるラベルと分岐の使用方法を示しています。

このコードは install_directory\examples\inline\strcopy.c に収録されて

います。

アセンブラブロック内のラベルの構文は、Cを使用した場合と同じです。インラインアセンブリ言語から BLを使用する関数呼び出しは、入力レジスタ、出力レジスタ、更新

レジスタを指定する必要があります。この例では、my_strcpy()への入力が aと bで

あり、出力はなく、デフォルトの ATPCSレジスタ、r0~ r3、r12、lr、PSRが更新されます。

例例例例 4-1 ストリングコピーストリングコピーストリングコピーストリングコピー

#include <stdio.h>

void my_strcpy(const char *src, char *dst){ int ch; __asm { loop:#ifndef __thumb // ARM version LDRB ch, [src], #1 STRB ch, [dst], #1#else

Page 64: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

C、C++、アセンブリ言語の混合

4-4 Copyright © 1999-2001 ARM Limited. All rights reserved. ARM DUI0056DJ-00

// Thumb version LDRB ch, [src] ADD src, #1 STRB ch, [dst] ADD dst, #1#endif CMP ch, #0 BNE loop }}

int main(void){ const char *a = "Hello world!"; char b[20]; my_strcpy (a, b); printf("Original string: '%s'\n", a); printf("Copied string: '%s'\n", b); return 0;}

4.1.2 ARM/Thumb命令セット命令セット命令セット命令セット

ARM命令セットと Thumb命令セットについては、ARM アーキテクチャリファレンスマニュアルで説明しています。全ての命令オペコードとレジスタ指定子は、小文字か大文字のどちらかで記述することができます。

オペランド式オペランド式オペランド式オペランド式

レジスタオペランドまたは定数オペランドは、変数の読み出しまたは書き込みが行えるように、任意の Cまたは C++式で表現することができます。この式は整数を代入できる式、つまり、char、short、intのいずれかのタイプでなければなりません。char

タイプと short タイプでは、符号拡張は行われません。これらのタイプについては、

符号拡張を明示的に行う必要があります。コンパイラは、これらの式を評価してレジスタに割り当てるためにコードを追加することがあります。

オペランドがデスティネーションとして使用されているとき、その式は代入可能(l値)でなければなりません。物理レジスタと式の両方を使用するコードを記述する場合には、評価にあまりにも多くのレジスタを必要とする複雑な式を使用しないように注意する必要があります。コンパイラは、レジスタの割り当て中に矛盾を検出すると、エラーメッセージを発行します。

Page 65: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

C、C++、アセンブリ言語の混合

ARM DUI0056DJ-00 Copyright © 1999-2001 ARM Limited. All rights reserved. 4-5

物理レジスタ物理レジスタ物理レジスタ物理レジスタ

インラインアセンブラは、制限されている物理レジスタへのアクセスを容認します。pcへの書き込みを行うことはできません。Bまたは BLを使用した分岐だけが許可されま

す。また、物理レジスタと、C または C++ の複雑な式を使用するインラインアセンブラ命令を混在させることは推奨できません。

コンパイラは C式を評価する際に、r12(ip)に加え、tccと tcppでは中間結果に r3を、関数呼び出しに r0 ~ r3、r12(ip)、r14(lr)を使用するため、これらのレジスタを同時に物理レジスタとして使用することはできません。

変数のように、物理レジスタを読み出すには事前に設定しておく必要があります。物理レジスタが使用されている場合、コンパイラは同一物理レジスタに割り当てられる可能性のある C/C++変数を保存・復元します。しかしコール標準では sp、sl、fp、sbに決まった役割が定義されているため、コンパイラはこれらのレジスタを復元することはできません。

注注注注

コンパイラによるレジスタの割り当てに制約が課され、効率性に欠けるコードが生成される可能性があるため、物理レジスタ名の使用は推奨できません。一般的には Cローカル変数を宣言し、インラインアセンブラでこれらをオペランドとして使用する方がより効果的です。

定数定数定数定数

定数式の指定子 # は省略可能です。この指定子を使用するとき、指定子の後に続ける

式は必ず定数でなければなりません。

命令の展開命令の展開命令の展開命令の展開

定数オペランドを使用する命令内の定数は、その命令に許される値だけに制限されません。代わりに、このような命令は同じ効果をもつ命令シーケンスに変換されます。例:

ADD r0, r0, #1023

これが以下のように変換される場合があります。

ADD r0, r0, #1024 SUB r0, r0, #1

コプロセッサ命令を除き、定数オペランドを使用する全ての ARM 命令と Thumb 命令は命令の展開をサポートしています。また、MUL 命令の第 3 オペランドが定数であるとき、この命令は加算とシフトのシーケンスに展開することができます。

展開された命令による CPSRの更新には、以下のような効果があります。

• 算術命令が NZCVフラグを正しくセットする。

Page 66: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

C、C++、アセンブリ言語の混合

4-6 Copyright © 1999-2001 ARM Limited. All rights reserved. ARM DUI0056DJ-00

• 論理命令が:

— NZフラグを正しくセットする。

— Vフラグを変更しない。

— Cフラグを更新する。

ラベルラベルラベルラベル

インラインアセンブラステートメントには、C または C++ で記述したラベルを使用することができます。Cまたは C++で記述したラベルには、以下の形式の分岐命令によってのみ分岐することができます。

B{cond} label

Cまたは C++ラベルに BLを使用して分岐することはできません。

記憶域の宣言記憶域の宣言記憶域の宣言記憶域の宣言

全ての記憶域は、C または C++ で宣言し、変数を使用してインラインアセンブラに渡すことができます。したがって、armasmにサポートされていない記憶域の宣言は実装されません。

SWI命令と命令と命令と命令と BL命令命令命令命令

SWI命令と BL命令では、使用するコール標準を正確に指定する必要があります。通常

の命令フィールドの後に、オプションで 3 つのレジスタリストを指定することができます。これらのレジスタリストでは以下を指定します。

• 入力パラメータを保持するレジスタ

• 復帰後の出力パラメータを保持するレジスタ

• 呼び出される関数によって更新されるレジスタ

例:

SWI{cond} swi_num, {input_regs}, {output_regs}, {corrupted_regs} BL{cond} function, {input_regs}, {output_regs}, {corrupted_regs}

省略したリストは空とみなされますが、BLは必ず ipと lrを更新します。BLによってデフォルトで更新されるレジスタは r0~ r3です。

これらのレジスタリストの構文は、LDM と STM のレジスタリストの構文と同じです。

NZCV フラグが変更されるときは、更新レジスタリスト内に PSR を指定する必要があります。

Page 67: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

C、C++、アセンブリ言語の混合

ARM DUI0056DJ-00 Copyright © 1999-2001 ARM Limited. All rights reserved. 4-7

4.1.3 インラインアセンブラとインラインアセンブラとインラインアセンブラとインラインアセンブラと armasmとの違いとの違いとの違いとの違い

インラインアセンブラに使用できるアセンブリ言語と、ARMアセンブラに使用できるアセンブリ言語には、数多くの相違点と制約条件があります。インラインアセンブラの場合:

• ピリオド(.)または {PC}を使用しても、現在の命令のアドレスを取得することはできません。

• LDR Rn, =expression擬似命令はサポートされていません。代わりにMOV Rn, expressionを使用して下さい(この命令によってリテラルプールからのロードが発生します)。

• ラベル式がサポートされていません。

• ADRおよび ADRL擬似命令がサポートされていません。

• & 演算子を使用して 16 進定数を表現することはできません。代わりに接頭文字0xを使用して下さい。例:

__asm {AND x, y, 0xF00}

• 8ビット定数の実ロテートを指定する表記は、インラインアセンブリ言語では使用できません。つまり、8ビットシフト定数が使用される場合には、NZCVフラグが更新されるのであれば、Cフラグは更新されるものとみなす必要があります。

• r0~ r3、ip、lrなどの物理レジスタと、CPSR内の NZCVフラグは、注意して使用する必要があります。Cまたは C++の式を使用する場合、これらのレジスタは一時レジスタとして使用される可能性があり、NZCVフラグは式を評価するときにコンパイラによって更新される可能性があります。

• 物理レジスタと同じ名前で C 変数を使用しないで下さい。__asm ブロック内でアクセスされるときは、C 変数の代わりに実レジスタが使用されます。(名前を括弧で囲むことによって C変数にアクセスすることも考えられますが、信頼性に欠けます。)

• LDM 命令と STM 命令では、レジスタリスト内に指定された物理レジスタだけが容認されます。

• pcへの書き込みを行うことはできません。BX命令と BLX命令は実装されません。

• スタックは修正すべきではありません。コンパイラが必要に応じて自動的に作業レジスタのスタックと復元を行うため、スタックを修正する必要はありません。作業レジスタのスタックと復元を明示的に行うことはできません。

Page 68: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

C、C++、アセンブリ言語の混合

4-8 Copyright © 1999-2001 ARM Limited. All rights reserved. ARM DUI0056DJ-00

• プロセッサモードの変更、ATPCSレジスタ fp、sl、sbの変更、コプロセッサ状態の変更はいずれも可能ですが、コンパイラはその変更を認識しません。プロセッサモードを変更する場合は、変更先のプロセッサモードのレジスタをコンパイラが更新するため、元のモードに戻るまでは C または C++ で記述した式を使用してはなりません。

同様に、浮動小数点命令の実行によって浮動小数点コプロセッサの状態を変更する場合は、元の状態が復元されるまで浮動小数点式を使用してはなりません。

Page 69: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

C、C++、アセンブリ言語の混合

ARM DUI0056DJ-00 Copyright © 1999-2001 ARM Limited. All rights reserved. 4-9

4.1.4 用法用法用法用法

インラインアセンブリ言語の使用には、以下の規則が適用されます。

• アセンブリ言語ではカンマを区切子として使用するため、カンマ演算子を使用する C式は、これと区別するために括弧で囲む必要があります。

__asm {ADD x, y, (f(), z)}

• 物理レジスタを使用する場合は、コンパイラが式を評価するときにこれらのレジスタを更新しないようにしておく必要があります。例:

__asm { MOV r0, x ADD y, r0, x / y // (x / y) overwrites r0 with the result.}

コンパイラは関数呼び出しを使用して x / yを評価するため、以下を行います。

— r2、r3、ip、lrを更新する。

— CPSR内の NZCVフラグを更新する。

— 被除数とモジュロで r0と r1を変更する。

r0 内の値が失われます。この問題は、r0 の代わりに C 変数を使用することで解決できます。

mov var,x add y, var, x / y

例えば、一時レジスタを必要としているときに、そのレジスタが既に使用されているときなど、コンパイラは多くの場合において更新を検出することができます。

__asm { MOV ip, #3 ADDS x, x, #0x12345678 // this instruction is expanded ORR x, x, ip }

ADD命令を展開するとき、コンパイラは ipを一時レジスタとして使用し、ip内の値 3を更新します。このときエラーメッセージが発行されます。

• 特定の変数が特定のレジスタにマップされることが明白であっても、変数のアドレス指定には物理レジスタを使用しないで下さい。コンパイラは、変数のアドレス指定に物理レジスタが使用されていることを検出するとエラーメッセージを生成するか、その変数を別のレジスタに配置して矛盾を回避します。

int bad_f(int x) // x in r0{ __asm { ADD r0, r0, #1 // wrongly asserts that x is still in r0

Page 70: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

C、C++、アセンブリ言語の混合

4-10 Copyright © 1999-2001 ARM Limited. All rights reserved. ARM DUI0056DJ-00

} return x; // x in r0}

このコードは xを変更しないまま返します。コンパイラは、xが関数のエントリ

とイグジットの両方で r0に割り当てられるにも関わらず、xと r0を 2つの異なる変数とみなします。アセンブリ言語コードは特に意味のあることは何もしないため、この動作はすぐに最適化されます。上記の命令は以下のように記述するべきです。

ADD x, x, #1

• インラインアセンブラに使用される物理レジスタの保存と復元は行わないで下さい。これらのレジスタの保存と復元はコンパイラが行います。CPSR と SPSR以外の物理レジスタが書き込まれてもいないのに読み出されると、エラーメッセージが発行されます。例:

int f(int x){ __asm { STMFD sp!, {r0} // save r0 - illegal: read before write ADD r0, x, 1 EOR x, r0, x LDMFD sp!, {r0} // restore r0 - not needed. } return x;}

Page 71: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

C、C++、アセンブリ言語の混合

ARM DUI0056DJ-00 Copyright © 1999-2001 ARM Limited. All rights reserved. 4-11

4.1.5 サンプルサンプルサンプルサンプル

例 4-2 ~ P. 4-13 例 4-5 は、インラインアセンブリ言語の効果的な使用方法を示しています。

割り込みのイネーブルとディセーブル割り込みのイネーブルとディセーブル割り込みのイネーブルとディセーブル割り込みのイネーブルとディセーブル

割り込みは、CPSRフラグの読み出しとビット 7の更新によってイネーブルまたはディセーブルされます。例 4-2は、これをインライン可能な小さな関数を使用して行う方法を示しています。

このコードは install_directory\examples\inline\irqs.c に収録されてい

ます。

CPSRと SPSRの制御ビットはユーザモードで変更できないため、これらの関数は特権モードにおいてのみ機能します。

例例例例 4-2 割り込み割り込み割り込み割り込み

__inline void enable_IRQ(void){ int tmp; __asm { MRS tmp, CPSR BIC tmp, tmp, #0x80 MSR CPSR_c, tmp }}

__inline void disable_IRQ(void){ int tmp; __asm { MRS tmp, CPSR ORR tmp, tmp, #0x80 MSR CPSR_c, tmp }}

int main(void){ disable_IRQ(); enable_IRQ();}

Page 72: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

C、C++、アセンブリ言語の混合

4-12 Copyright © 1999-2001 ARM Limited. All rights reserved. ARM DUI0056DJ-00

ドット積ドット積ドット積ドット積

例 4-3では、2つの整数配列のドット積を計算します。この例は、Cまたは C++で記述した式と、インラインアセンブラに直接サポートされていないデータタイプに対し、インラインアセンブリ言語でどのようにインターワーキングできるかを示しています。インライン関数 mlal()は、1つの SMLAL命令に最適化されます。-S -fsコンパイラオプションを使用すると、コンパイラによって生成されるアセンブラ言語コードを見ることができます。

long longは、__int64と同じことです。

このコードは install_directory\examples\inline\dotprod.c に収録されて

います。

例例例例 4-3 ドット積ドット積ドット積ドット積

#include <stdio.h>/* change word order if big-endian#define lo64(a) (((unsigned*) &a)[0]) /* low 32 bits of a long long */#define hi64(a) (((int*) &a)[1]) /* high 32 bits of a long long */

__inline __int64 mlal(__int64 sum, int a, int b){#if !defined(__thumb) && defined(__TARGET_FEATURE_MULTIPLY) __asm { SMLAL lo64(sum), hi64(sum), a, b }#else sum += (__int64) a * (__int64) b;#endif return sum;}

__int64 dotprod(int *a, int *b, unsigned n){ __int64 sum = 0; do sum = mlal(sum, *a++, *b++); while (--n != 0); return sum;}int a[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };int b[10] = { 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 };int main(void){ printf("Dotproduct %lld (should be %d)\n", dotprod(a, b, 10), 220); return 0;}

Page 73: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

C、C++、アセンブリ言語の混合

ARM DUI0056DJ-00 Copyright © 1999-2001 ARM Limited. All rights reserved. 4-13

ロング乗算ロング乗算ロング乗算ロング乗算

インラインアセンブラを使用して、long long タイプの関数をカスタマイズすることができます。例 4-4は、Cで記述した単純なロング乗算ルーチンを示しています。

例 4-5は、インラインアセンブリ言語を使用して、同じルーチンで違うコードを生成する方法を示しています。インラインアセンブラを使用すれば、long long の上位ワードと下位ワードを別々に記述することができます。

インラインアセンブリ言語コードは、下位 32ビットがオフセット 0にあるとみなすため、long longタイプのワード順序に依存します。

このコードは install_directory\examples\inline\smull.c に収録されてい

ます。

例例例例 4-4 Cを使用した乗算を使用した乗算を使用した乗算を使用した乗算

乗算ルーチンを Cで記述した場合:

// long multiply routine in Clong long smull(int x, int y){ return (long long) x * (long long) y;}

コンパイラは以下のコードを生成します。

MOV r2,r0 MOV r0,r1 MOV r1,r2 SMULL r12,r1,r0,r2 MOV r0,r12 MOV pc,lr

このルーチンでは r12が更新されます。ATPCSではこの更新が可能です。

例例例例 4-5 インラインアセンブリ言語を使用した乗算インラインアセンブリ言語を使用した乗算インラインアセンブリ言語を使用した乗算インラインアセンブリ言語を使用した乗算

上記と同じルーチンをインラインアセンブリ言語で記述した場合:

long long smull(int x, int y){ long long res; __asm { SMULL ((int*)&res)[0], ((int*)&res)[1], x, y } return res;}

Page 74: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

C、C++、アセンブリ言語の混合

4-14 Copyright © 1999-2001 ARM Limited. All rights reserved. ARM DUI0056DJ-00

コンパイラは以下のコードを生成します。

MOV r2,r0 SMULL r0,r1,r2,r1 MOV pc,lr

Page 75: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

C、C++、アセンブリ言語の混合

ARM DUI0056DJ-00 Copyright © 1999-2001 ARM Limited. All rights reserved. 4-15

4.2 アセンブリコードからアセンブリコードからアセンブリコードからアセンブリコードから Cグローバル変数へのアクセスグローバル変数へのアクセスグローバル変数へのアクセスグローバル変数へのアクセス

グローバル変数には、それらのアドレスを使用して間接的にアクセスすることしかできません。グローバル変数にアクセスするには、IMPORTディレクティブを使用してグ

ローバル変数をインポートし、そのアドレスをレジスタにロードします。この変数には、そのタイプによって、ロード /ストア命令を使用してアクセスすることができます。

unsigned変数の場合には、以下を使用します。

• charタイプには LDRB/STRB

• shortタイプには LDRH/STRH(アーキテクチャ3では 2つの LDRB/STRB命令を使用して下さい。)

• intタイプには LDR/STR

signed変数の場合は、LDRSBやLDRSHなどの上記と等価な符号付き命令を使用して下

さい。

8 ワード未満の小さな構造には、LDM 命令と STM 命令を使用して構造全体としてアク

セスすることができます。構造の各メンバには、適切なタイプのロード /ストア命令でアクセスすることができます。各メンバにアクセスするには、構造の開始位置からのメンバのオフセットを知っておく必要があります。

例 4-6では、整数グローバル globvarのアドレスを r1にロードし、そのアドレスが保持する値を r0にロードし、これに 2を加算し、得られた値を globvarに返します。

例例例例 4-6 グローバル変数のアドレスグローバル変数のアドレスグローバル変数のアドレスグローバル変数のアドレス

AREA globals,CODE,READONLY

EXPORT asmsubroutine IMPORT globvar

asmsubroutine LDR r1, =globvar ; read address of globvar into ; r1 from literal pool LDR r0, [r1] ADD r0, r0, #2 STR r0, [r1] MOV pc, lr END

Page 76: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

C、C++、アセンブリ言語の混合

4-16 Copyright © 1999-2001 ARM Limited. All rights reserved. ARM DUI0056DJ-00

4.3 C++からのからのからのからの Cヘッダファイルの使用ヘッダファイルの使用ヘッダファイルの使用ヘッダファイルの使用

このセクションでは、C++コードから Cヘッダファイルを使用する方法を説明します。C++ から C ヘッダファイルを呼び出す前に、このファイルを extern "C" ディレク

ティブでラップする必要があります。

4.3.1 システムシステムシステムシステム Cヘッダファイルのインクルードヘッダファイルのインクルードヘッダファイルのインクルードヘッダファイルのインクルード

stdio.hなどの標準システムCヘッダファイルをインクルードするときは、特に何もする必要はありません。標準 Cヘッダファイルには、既に適切な extern "C"ディレク

ティブが含まれています。例:

// C++ code

#include <stdio.h>int main(){ //... return 0;}

C++標準では、Cヘッダファイルの機能を C++で記述した特定のヘッダファイルから使用できることが定義されています。これらのファイルは標準 C ヘッダファイルと一緒に install_directory\includeにインストールされ、通常の方法で参照するこ

とができます。例:

// C++ code

#include <cstdio>int main(){ // ... return 0;}

ARM C++では、これらのヘッダは単純に Cヘッダを #includeします。

注注注注

C 標準ヘッダファイルと、これらに使用する C++ ベニアヘッダは、コンパイラのインメモリファイルシステムにあります。詳細については、ADSコンパイラ /ライブラリガイドの「Cコンパイラ」を参照して下さい。

Page 77: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

C、C++、アセンブリ言語の混合

ARM DUI0056DJ-00 Copyright © 1999-2001 ARM Limited. All rights reserved. 4-17

4.3.2 作成した作成した作成した作成した Cヘッダファイルのインクルードヘッダファイルのインクルードヘッダファイルのインクルードヘッダファイルのインクルード

自分で作成した C ヘッダファイルをインクルードするには、#include ディレクティブを extern "C"ステートメントでラップする必要があります。この作業は以下の 2

つの方法で行うことができます。

• ファイルが #includedされるとき(例 4-7参照)

• extern "C"ステートメントをヘッダファイルに追加する(例 4-8参照)。

例例例例 4-7 インクルードファイルの前にディレクティブを配置するインクルードファイルの前にディレクティブを配置するインクルードファイルの前にディレクティブを配置するインクルードファイルの前にディレクティブを配置する

// C++ code

extern "C"{#include "my-header1.h"#include "my-header2.h"}

int main(){ // ... return 0;}

例例例例 4-8 ディレクティブをファイルヘッダ内に配置するディレクティブをファイルヘッダ内に配置するディレクティブをファイルヘッダ内に配置するディレクティブをファイルヘッダ内に配置する

/* C header file */

#ifdef __cplusplus /* Insert start of extern C construct */extern "C" {#endif

/* Body of header file */

#ifdef __cplusplus /* Insert end of extern C construct */} /* The C header file can now be */#endif /* included in either C or C++ code. */

Page 78: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

C、C++、アセンブリ言語の混合

4-18 Copyright © 1999-2001 ARM Limited. All rights reserved. ARM DUI0056DJ-00

4.4 C、、、、C++、アセンブリ言語間の呼び出し、アセンブリ言語間の呼び出し、アセンブリ言語間の呼び出し、アセンブリ言語間の呼び出し

このセクションでは、C++から Cおよびアセンブリ言語コードを呼び出すとき、また Cおよびアセンブリ言語から C++コードを呼び出すときに役立つサンプルを紹介します。その他、呼び出し規則とデータタイプについても説明します。

C、C++、アセンブリ言語で記述したルーチン間の呼び出しは混在させることができますが、適切な ATPCSプロシージャコール標準に準拠している必要があります。ATPCSの詳細については、第 2章「プロシージャコール標準の使用」を参照して下さい。

注注注注

このセクションの情報は実装に依存するものであり、本ツールキットの今後のバージョンでは変更される可能性があります。

4.4.1 複数言語間の呼び出しに関する一般規則複数言語間の呼び出しに関する一般規則複数言語間の呼び出しに関する一般規則複数言語間の呼び出しに関する一般規則

C、C++、アセンブリ言語間の呼び出しには、以下の一般規則が適用されます。

以下に示した C++の実装に関する情報には依存しないで下さい。これらの実装情報は、ARM C++の今後のバージョンで変更される可能性があります。

• 名前の符号化に使用される方法

• 暗黙の thisパラメータが渡されるときの方法

• 仮想関数の呼び出し方

• 参照の表現

• ベースクラスまたは仮想メンバ関数をもつ C++クラスタイプのレイアウト

• プレーンオールドデータ(POD)構造ではないクラスオブジェクトの受け渡し方

混合言語プログラミングには以下の一般規則が適用されます。

• C呼び出し規則を使用すること

• C++では、非メンバ関数を extern "C"として宣言し、Cリンケージがあることを指定できる。ADSの本リリースでは、Cリンケージを使用すると、その関数を定義するシンボルは符号化されません。Cリンケージは、1つの言語で記述した関数を実装し、それを別の言語から呼び出す目的で使用することができます。

注注注注

extern "C"で宣言する関数は、多重定義できません。

• アセンブリ言語モジュールは、そのアプリケーションに使用されるメモリモデルに適した ARM/Thumbプロシージャコール標準に準拠している必要がある。

Page 79: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

C、C++、アセンブリ言語の混合

ARM DUI0056DJ-00 Copyright © 1999-2001 ARM Limited. All rights reserved. 4-19

Cおよびアセンブリ言語からの C++の呼び出しには、以下の規則が適用されます。

• グローバル(非メンバ)C++関数を呼び出すには、これを extern "C"で宣言して Cリンケージを与える必要がある。

• メンバ関数(スタティック、非スタティックともに)は常に符号化された名前をもつ。

• C++インライン関数は、C++コンパイラがその関数と不揃いのコピーを生成することが明白でない限り、Cから呼び出すことはできない。例えば、この関数のアドレスが取得されると、不揃いのコピーが生成されます。

• 非スタティックメンバ関数は、暗黙の thisパラメータを r0内の最初の引数として、あるいはこの関数が非整数ライクな構造に戻るときは r1 内の 2 番目の引数として受け取る。この規則は、今後のリリースでは変更される可能性があります。スタティックメンバ関数は、暗黙の thisパラメータを受け取りません。

4.4.2 C++固有の情報固有の情報固有の情報固有の情報

以下は、C++だけに適用されます。

C++呼び出し規則呼び出し規則呼び出し規則呼び出し規則

ARM C++は、以下の例外を除き、ARM Cと同じ呼び出し規則を使用します。

• struct または class タイプのオブジェクトが関数に渡され、そのオブジェクトが明示的なコピー構成子である場合、そのオブジェクトは呼び出し元のコードまたはサブルーチン(呼び出し先)によってコピーされる。この構成子が多重定義されていると、呼び出し元がそのコピーを作成します。この構成子が多重定義されていなければ、呼び出し先がそのコピーを作成します。

• 非スタティックメンバ関数は、暗黙の thisパラメータを最初の引数として、あるいは呼び出される関数が非整数structに戻るときは 2番目の引数として使用することで呼び出される。この規則は、今後のリリースでは変更される可能性があります。

C++データタイプデータタイプデータタイプデータタイプ

ARM C++は、以下の例外と追加点を除き、ARM Cと同じデータタイプを使用します。

• structまたは classクラスの C++オブジェクトには、ベースクラスも仮想関数も含まれていない場合に限り、ARM C コンパイラを使用したときに予想されるレイアウトと同じレイアウトが使用される。このような structに、ユーザ定義のコピー代入演算子とユーザ定義の破壊子がどちらも含まれていなければ、それは POD構造です。

• 参照はポインタとして表現される。

Page 80: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

C、C++、アセンブリ言語の混合

4-20 Copyright © 1999-2001 ARM Limited. All rights reserved. ARM DUI0056DJ-00

• データメンバへのポインタと、メンバ関数へのポインタには、4バイトが使用される。NULLポインタには通常のポインタと同じ表現が使用されます。

• C関数へのポインタと、C++(非メンバ)関数へのポインタは区別されない。

シンボル名の符号化シンボル名の符号化シンボル名の符号化シンボル名の符号化

ARM C++は、関数とスタティックデータメンバの外部名を、Ellis, M.A. and Stroustrup,B.著「The Annotated C++ Reference Manual(1990年発行)」のセクション 7.2cで説明されている方法と同じような方法で符号化します。リンカはシンボルをメッセージ内で復号化します。

C で記述する名前は、C++ プログラムでは extern "C" で宣言する必要があります。

ARM ANSI C ヘッダでは、この宣言が既に行われています。詳細については、P. 4-16「C++からの Cヘッダファイルの使用」を参照して下さい。

4.4.3 サンプルサンプルサンプルサンプル

このセクションでは、以下を示すサンプルコードを紹介します。

• Cからのアセンブリ言語の呼び出し

• アセンブリ言語からの Cの呼び出し:P. 4-21

• C++からの Cの呼び出し:P. 4-22

• C++からのアセンブリ言語の呼び出し:P. 4-23

• Cからの C++の呼び出し:P. 4-24

• アセンブリ言語からの C++の呼び出し:P. 4-24

• Cまたはアセンブリ言語からの C++の呼び出し:P. 4-26

• Cと C++間の参照の受け渡し:P. 4-25

これらのサンプルでは、スタックのオーバフローをチェックせずにスタック演算を実行するため、デフォルトのソフトウェアスタックチェックを無効にした ATPCSバリアントの使用を前提としています。

Cからのアセンブリ言語の呼び出しからのアセンブリ言語の呼び出しからのアセンブリ言語の呼び出しからのアセンブリ言語の呼び出し

例 4-9および P. 4-21例 4-10は、1つのストリングを別のストリングの上にコピーするアセンブリ言語サブルーチンへの呼び出しを使用する Cプログラムを示しています。

例例例例 4-9 Cからのアセンブリ言語の呼び出しからのアセンブリ言語の呼び出しからのアセンブリ言語の呼び出しからのアセンブリ言語の呼び出し

#include <stdio.h>extern void strcopy(char *d, const char *s);int main(){ const char *srcstr = "First string - source "; char dststr[] = "Second string - destination ";

Page 81: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

C、C++、アセンブリ言語の混合

ARM DUI0056DJ-00 Copyright © 1999-2001 ARM Limited. All rights reserved. 4-21

/* dststr is an array since we’re going to change it */ printf("Before copying:\n"); printf(" %s\n %s\n",srcstr,dststr); strcopy(dststr,srcstr); printf("After copying:\n"); printf(" %s\n %s\n",srcstr,dststr); return (0);}

例例例例 4-10 アセンブリ言語で記述したストリングコピーサブルーチンアセンブリ言語で記述したストリングコピーサブルーチンアセンブリ言語で記述したストリングコピーサブルーチンアセンブリ言語で記述したストリングコピーサブルーチン

AREA SCopy, CODE, READONLY EXPORT strcopystrcopy ; r0 points to destination string. ; r1 points to source string. LDRB r2, [r1],#1 ; Load byte and update address. STRB r2, [r0],#1 ; Store byte and update address. CMP r2, #0 ; Check for zero terminator. BNE strcopy ; Keep going if not. MOV pc,lr ; Return. END

P. 4-20 例 4-9 のコードは、install_directory\examples\asm ディレクトリの

strtest.cおよび scopy.sに収録されています。以下のステップに従って、このサン

プルをコマンドラインからビルドして下さい。

1. armasm -g scopy.sを入力し、このアセンブリ言語ソースをビルドします。

2. armcc -c -g strtest.cを入力し、Cソースをビルドします。

3. armlink strtest.o scopy.o -o strtestを入力し、これらのオブジェクトファイルをリンクさせます。

4. armsd -e strtestを入力し、このサンプルを実行します。

アセンブリ言語からのアセンブリ言語からのアセンブリ言語からのアセンブリ言語からの Cの呼び出しの呼び出しの呼び出しの呼び出し

P. 4-22例 4-11および例 4-12は、アセンブリ言語からCを呼び出す方法を示しています。

Page 82: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

C、C++、アセンブリ言語の混合

4-22 Copyright © 1999-2001 ARM Limited. All rights reserved. ARM DUI0056DJ-00

例例例例 4-11 Cによる関数の定義による関数の定義による関数の定義による関数の定義

int g(int a, int b, int c, int d, int e) { return a + b + c + d + e;}

例例例例 4-12 アセンブリ言語による呼び出しアセンブリ言語による呼び出しアセンブリ言語による呼び出しアセンブリ言語による呼び出し

; int f(int i) { return g(i, 2*i, 3*i, 4*i, 5*i); }

EXPORT f AREA f, CODE, READONLY IMPORT g ; i is in r0 STR lr, [sp, #-4]! ; preserve lr ADD r1, r0, r0 ; compute 2*i (2nd param) ADD r2, r1, r0 ; compute 3*i (3rd param) ADD r3, r1, r2 ; compute 5*i STR r3, [sp, #-4]! ; 5th param on stack ADD r3, r1, r1 ; compute 4*i (4th param) BL g ; branch to C function ADD sp, sp, #4 ; remove 5th param LDR pc, [sp], #4 ; return END

C++からのからのからのからの Cの呼び出しの呼び出しの呼び出しの呼び出し

例 4-13および P. 4-23例 4-14は、C++から Cを呼び出す方法を示しています。

例例例例 4-13 C++からのからのからのからの C関数の呼び出し関数の呼び出し関数の呼び出し関数の呼び出し

struct S { // has no base classes // or virtual functions S(int s) : i(s) { } int i;};extern "C" void cfunc(S *); // declare the C function to be called from C++int f(){ S s(2); // initialize 's'

Page 83: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

C、C++、アセンブリ言語の混合

ARM DUI0056DJ-00 Copyright © 1999-2001 ARM Limited. All rights reserved. 4-23

cfunc(&s); // call 'cfunc' so it can change 's' return s.i * 3;}

例例例例 4-14 Cによる関数の定義による関数の定義による関数の定義による関数の定義

struct S { int i;};void cfunc(struct S *p) {/* the definition of the C function to be called from C++ */ p->i += 5;}

C++からのアセンブリ言語の呼び出しからのアセンブリ言語の呼び出しからのアセンブリ言語の呼び出しからのアセンブリ言語の呼び出し

例 4-15および例 4-16は、C++からアセンブリ言語を呼び出す方法を示しています。

例例例例 4-15 C++からのアセンブリ言語の呼び出しからのアセンブリ言語の呼び出しからのアセンブリ言語の呼び出しからのアセンブリ言語の呼び出し

struct S { // has no base classes // or virtual functions S(int s) : i(s) { } int i;};

extern "C" void asmfunc(S *); // declare the Asm function // to be calledint f() { S s(2); // initialize 's' asmfunc(&s); // call 'asmfunc' so it // can change 's' return s.i * 3;}

例例例例 4-16 アセンブリ言語による関数の定義アセンブリ言語による関数の定義アセンブリ言語による関数の定義アセンブリ言語による関数の定義

AREA Asm, CODE EXPORT asmfuncasmfunc ; the definition of the Asm LDR r1, [r0] ; function to be called from C++

Page 84: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

C、C++、アセンブリ言語の混合

4-24 Copyright © 1999-2001 ARM Limited. All rights reserved. ARM DUI0056DJ-00

ADD r1, r1, #5 STR r1, [r0] MOV pc, lr END

Cからのからのからのからの C++の呼び出しの呼び出しの呼び出しの呼び出し

例 4-17および例 4-18は、Cから C++を呼び出す方法を示しています。

例例例例 4-17 C++による呼び出される関数の定義による呼び出される関数の定義による呼び出される関数の定義による呼び出される関数の定義

struct S { // has no base classes or virtual functions S(int s) : i(s) { } int i;};

extern "C" void cppfunc(S *p) { // Definition of the C++ function to be called from C.// The function is written in C++, only the linkage is C p->i += 5; //}

例例例例 4-18 Cによる関数の宣言と呼び出しによる関数の宣言と呼び出しによる関数の宣言と呼び出しによる関数の宣言と呼び出し

struct S { int i;};

extern void cppfunc(struct S *p); /* Declaration of the C++ function to be called from C */

int f(void) { struct S s; s.i = 2; /* initialize 's' */ cppfunc(&s); /* call 'cppfunc' so it */ /* can change 's' */ return s.i * 3;}

アセンブリ言語からのアセンブリ言語からのアセンブリ言語からのアセンブリ言語からの C++の呼び出しの呼び出しの呼び出しの呼び出し

P. 4-25例4-19および例4-20は、アセンブリ言語からC++を呼び出す方法を示しています。

Page 85: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

C、C++、アセンブリ言語の混合

ARM DUI0056DJ-00 Copyright © 1999-2001 ARM Limited. All rights reserved. 4-25

例例例例 4-19 C++による呼び出される関数の定義による呼び出される関数の定義による呼び出される関数の定義による呼び出される関数の定義

struct S { // has no base classes or virtual functions S(int s) : i(s) { } int i;};extern "C" void cppfunc(S * p) {// Definition of the C++ function to be called from ASM.// The body is C++, only the linkage is C p->i += 5;}

ARMアセンブリ言語では、C++関数の名前をインポートし、リンク付き分岐命令を使用してこれを呼び出します。

例例例例 4-20 アセンブリ言語による関数の定義アセンブリ言語による関数の定義アセンブリ言語による関数の定義アセンブリ言語による関数の定義

AREA Asm, CODE IMPORT cppfunc ; import the name of the C++ ; function to be called from Asm

EXPORT ff STMFD sp!,{lr} MOV r0,#2 STR r0,[sp,#-4]! ; initialize struct MOV r0,sp ; argument is pointer to struct BL cppfunc ; call 'cppfunc' so it can change ; the struct LDR r0, [sp], #4 ADD r0, r0, r0,LSL #1 LDMFD sp!,{pc} END

Cとととと C++間の参照の受け渡し間の参照の受け渡し間の参照の受け渡し間の参照の受け渡し

P. 4-26例 4-21および例 4-22は、Cと C++間の参照の受け渡し方法を示しています。

Page 86: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

C、C++、アセンブリ言語の混合

4-26 Copyright © 1999-2001 ARM Limited. All rights reserved. ARM DUI0056DJ-00

例例例例 4-21 C++関数関数関数関数

extern "C" int cfunc(const int&); // Declaration of the C function to be called from C++

extern "C" int cppfunc(const int& r) {// Definition of the C++ to be called from C. return 7 * r;}

int f() { int i = 3; return cfunc(i); // passes a pointer to 'i'}

例例例例 4-22 C関数の定義関数の定義関数の定義関数の定義

extern int cppfunc(const int*); /* declaration of the C++ to be called from C */

int cfunc(const int* p) { /* definition of the C function to be called from C++ */ int k = *p + 4; return cppfunc(&k);}

Cまたはアセンブリ言語からのまたはアセンブリ言語からのまたはアセンブリ言語からのまたはアセンブリ言語からの C++の呼び出しの呼び出しの呼び出しの呼び出し

例 4-23および P. 4-27例 4-24、例 4-25のコードは、非スタティックな、非仮想 C++関数を C またはアセンブリ言語から呼び出す方法を示しています。この関数の符号化された名前を見るには、コンパイラからのアセンブラ出力を使用して下さい。

例例例例 4-23 C++メンバ関数の呼び出しメンバ関数の呼び出しメンバ関数の呼び出しメンバ関数の呼び出し

struct T { T(int i) : t(i) { } int t; int f(int i);};

int T::f(int i) { return i + t; } // Definition of the C++ function to be called from C.

Page 87: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

C、C++、アセンブリ言語の混合

ARM DUI0056DJ-00 Copyright © 1999-2001 ARM Limited. All rights reserved. 4-27

extern "C" int cfunc(T*); // declaration of the C function to be called from C++

int f() { T t(5); // create an object of type T return cfunc(&t);}

例例例例 4-24 C関数の定義関数の定義関数の定義関数の定義

struct T;

extern int f__1TFi(struct T*, int); /* the mangled name of the C++ */ /* function to be called */

int cfunc(struct T* t) { /* Definition of the C function to be called from C++. */ return 3 * f__1TFi(t, 2); /* like '3 * t->f(2)' */}

例例例例 4-25 アセンブリ言語による関数の実装アセンブリ言語による関数の実装アセンブリ言語による関数の実装アセンブリ言語による関数の実装

EXPORT cfunc AREA cfunc, CODE IMPORT f__1TFi STMFD sp!,{lr} ; r0 already contains the object pointer MOV r1, #2 BL f__1TFi ADD r0, r0, r0, LSL #1 ; multiply by 3 LDMFD sp!,{pc} END

Page 88: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

C、C++、アセンブリ言語の混合

4-28 Copyright © 1999-2001 ARM Limited. All rights reserved. ARM DUI0056DJ-00

Page 89: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

ARM DUI0056DJ-00 Copyright © 1999-2001 ARM Limited. All rights reserved. 5-1

第 5章プロセッサ例外処理プロセッサ例外処理プロセッサ例外処理プロセッサ例外処理

本章では、ARMプロセッサがサポートしている各種例外の処理方法について説明します。本章は以下のセクションから構成されています。

• プロセッサ例外について:P. 5-2

• 例外の開始と終了:P. 5-5

• 例外ハンドラのインストール:P. 5-9

• SWIハンドラ:P. 5-14

• 割り込みハンドラ:P. 5-23

• リセットハンドラ:P. 5-33

• 未定義命令ハンドラ:P. 5-34

• プリフェッチアボートハンドラ:P. 5-35

• データアボートハンドラ:P. 5-36

• 例外ハンドラのチェインニング:P. 5-38

• Thumb対応プロセッサでの例外処理:P. 5-40

• システムモード:P. 5-45

Page 90: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

プロセッサ例外処理

5-2 Copyright © 1999-2001 ARM Limited. All rights reserved. ARM DUI0056DJ-00

5.1 プロセッサ例外についてプロセッサ例外についてプロセッサ例外についてプロセッサ例外について

プログラムの通常の実行フローにおいては、近くのラベルへの分岐や、サブルーチンへの分岐とリンクなどを経て、プログラムカウンタはそのアドレス空間にわたってシーケンシャルに増加していきます。

プロセッサ例外は、内部ソースまたは外部ソースに生成されたイベントをプロセッサが処理できるように、この通常の実行フローが迂回されるときに発生します。このイベントには以下のようなものがあります。

• 外部で生成された割り込み

• 未定義命令を実行しようとするプロセッサの試行

• 特権付きオペレーティングシステム関数へのアクセス

このような例外を処理するときは、それまでのプロセッサ状態を保存しておく必要があるため、例外発生時に行われていたプログラムの実行は、適切な例外ルーチンの終了時に再開させることができます。

表 5-1は、ARMプロセッサが認識する 7タイプの例外を示しています。

表表表表 5-1 例外のタイプ例外のタイプ例外のタイプ例外のタイプ

例外例外例外例外 説明説明説明説明

リセット プロセッサリセットピンがアサートされると発生します。この例外は、起動を通知するため、あるいはプロセッサがたった今起動したばかりであるかのようにリセットするためだけに発生することが予想されます。ソフトリセットは、リセットベクタ(0x0000)への分岐によって発生させることができます。

未定義命令 現在実行中の命令が、プロセッサにも接続されているどのコプロセッサにも認識されない場合に発生します。

ソフトウェア割り込み(SWI)

ユーザ定義の同期割り込み命令です。ソフトウェア割り込みにより、例えばユーザモードで実行中のプログラムが、RTOS関数などのスーパバイザモードで実行する特権命令を要求することができます。

プリフェッチアボート プロセッサが、アドレスが不正であったためにフェッチされなかった命令をを実行しようとしたときに発生します。a

データアボート データ転送命令が不正アドレスでのロードまたはストアを試行したときに発生します。a

IRQ プロセッサ外部割り込み要求ピンが LOWでアサートされ、かつ CPSR内の Iビットがクリアされているときに発生します。

FIQ プロセッサ外部高速割り込み要求ピンが LOWでアサートされ、かつ CPSR内の Fビットがクリアされているときに発生します。

a. 不正仮想アドレスとは、その時点で物理メモリ内のアドレスに対応していないアドレス、あるいはメモリ管理サブシステムによってプロセッサが現在のモードではアクセスできないと判断されたアドレスを指します。

Page 91: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

プロセッサ例外処理

ARM DUI0056DJ-00 Copyright © 1999-2001 ARM Limited. All rights reserved. 5-3

5.1.1 ベクタテーブルベクタテーブルベクタテーブルベクタテーブル

プロセッサ例外処理はベクタテーブルによって制御されます。ベクタテーブルは 32バイトの予約エリアであり、通常はメモリマップの最下位に配置されます。ベクタテーブルでは各例外タイプに1ワードの空間が割り当てられ、1ワードが予約されています。

この空間ではハンドラのコード全体を保持するには不十分であるため、一般的に各例外タイプのベクタエントリは適切なハンドラを使用して実行を継続するための分岐命令またはロード pc命令を保持します。

5.1.2 例外によるモードとレジスタの使用例外によるモードとレジスタの使用例外によるモードとレジスタの使用例外によるモードとレジスタの使用

通常、アプリケーションはユーザモードで実行しますが、例外処理には特権(非ユーザモードの)動作が必要となります。例外が発生するとプロセッサモードが変更され、これにより各例外ハンドラは特定のバンクレジスタのサブセットにアクセスできるようになります。

• 専用の r13またはスタックポインタ(sp_mode)

• 専用の r14またはリンクレジスタ(lr_mode)

• 専用の保存プログラムステータスレジスタ(spsr_ mode)

FIQの場合、各例外ハンドラはさらに 5つの汎用レジスタ(r8_FIQ~ r12_FIQ)にアクセスできます。

各例外ハンドラは、イグジットで他のレジスタを元の内容に復元させる必要があります。この操作は、ハンドラが必要とする全てのレジスタの内容をスタックに保存し、復帰前にこれらを復元することで可能となります。Angel™または ARMulator®を使用すれ

ば、必要となるスタックが自動的に設定されます。これらを使用しない場合は、スタックを自分自身で設定する必要があります。詳細については、第 6章「ROMコードの記述」を参照して下さい。

注注注注

前述のとおり、アセンブラは register_mode 形式のシンボリックなレジスタ名を事前宣言しません。この形式を使用するには、RNアセンブラディレクティブを使用して、適切なシンボリック名を宣言する必要があります。例えば、lr_FIQ RN r14 を使用すると、r14 のシンボリックレジスタ名 lr_FIQ を宣言できます。RN ディレクティブの詳細については、ADSアセンブラガイドのディレクティブの章を参照して下さい。

5.1.3 例外の優先度例外の優先度例外の優先度例外の優先度

複数の例外が同時に発生すると、これらの例外は決まった優先度順に処理されます。各例外は、ユーザプログラムの実行が継続されるまでに順番に処理されます。全ての例外が同時に発生することはあり得ません。例えば、未定義命令例外と SWI例外は、どちらもある命令の実行によってトリガされるため、相互排他的です。

Page 92: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

プロセッサ例外処理

5-4 Copyright © 1999-2001 ARM Limited. All rights reserved. ARM DUI0056DJ-00

表 5-2 は、例外と対応するプロセッサモード、ならびにその処理の優先度を示しています。

データアボート例外は FIQ 例外よりも優先されるため、データアボートが実際に登録されてから FIQ が処理されます。データアボートハンドラが開始されても、制御はすぐに FIQ ハンドラに渡されます。FIQ が処理されると、制御はデータアボートハンドラに戻ります。FIQが先に処理されるとデータ転送エラーが検出されませんが、この方法によってデータ転送エラーは必ず検出されます。

表表表表 5-2 例外の優先度例外の優先度例外の優先度例外の優先度

ベクタアドレスベクタアドレスベクタアドレスベクタアドレス 例外タイプ例外タイプ例外タイプ例外タイプ 例外モード例外モード例外モード例外モード 優先度(優先度(優先度(優先度(1=高、高、高、高、6=低)=低)=低)=低)

0x0 Reset スーパバイザ(SVC) 1

0x4 Undefined Instruction Undef 6

0x8 ソフトウェア割り込み(SWI) スーパバイザ(SVC) 6

0xC プリフェッチアボート アボート 5

0x10 データアボート アボート 2

0x14 予約 なし なし

0x18 割り込み(IRQ) 割り込み(IRQ) 4

0x1C 高速割り込み(FIQ) 高速割り込み(FIQ) 3

Page 93: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

プロセッサ例外処理

ARM DUI0056DJ-00 Copyright © 1999-2001 ARM Limited. All rights reserved. 5-5

5.2 例外の開始と終了例外の開始と終了例外の開始と終了例外の開始と終了

このセクションでは、例外に対するプロセッサの応答と、例外処理後に例外発生時の場所に戻る方法を説明します。この復帰方法は、例外タイプによって異なります。

5.2.1 例外に対するプロセッサの応答例外に対するプロセッサの応答例外に対するプロセッサの応答例外に対するプロセッサの応答

例外が生成されると、プロセッサは以下を行います。

1. カレントプログラムステータスレジスタ(CPSR)を、例外が処理されるモードの保存プログラムステータスレジスタ(SPSR)にコピーします。これにより、現在のモード、割り込みマスク、条件フラグが保存されます。

2. 以下を行うために、適切な CPSRモードビットを変更します。

• 適切なモードに切り替え、そのモードの適切なバンクレジスタにマップする。

• 割り込みをディセーブルする。どの例外が発生しても IRQはディセーブルされます。FIQは FIQが発生したときと、リセット時にディセーブルされます。

3. lr_modeに復帰アドレスをセットします(P. 5-7「復帰アドレスと復帰命令」参照)。

4. プログラムカウンタに、その例外のベクタアドレスをセットします。これにより、適切な例外ハンドラへの分岐を発生させます。

注注注注

アプリケーションが Thumb対応プロセッサで実行されている場合には、プロセッサの応答が若干異なります。詳細については、P. 5-40「Thumb 対応プロセッサでの例外処理」を参照して下さい。

Page 94: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

プロセッサ例外処理

5-6 Copyright © 1999-2001 ARM Limited. All rights reserved. ARM DUI0056DJ-00

5.2.2 例外ハンドラからの復帰例外ハンドラからの復帰例外ハンドラからの復帰例外ハンドラからの復帰

例外からの復帰方法は、例外ハンドラがスタック操作を行うかどうかによって異なります。いずれの場合も、実行を例外発生時の場所に戻すには、例外ハンドラが以下を行う必要があります。

• spsr_modeから CPSRを復元する。

• lr_mode に保存されている復帰アドレスを使用してプログラムカウンタを復元する。

デスティネーションモードのレジスタをスタックから復元する必要のない単純な復帰では、例外ハンドラは以下を使用するデータ処理命令を実行することによって、上記の 2つの操作を行います。

• セットされた Sフラグ

• プログラムカウンタをデスティネーションレジスタとして

必要な復帰命令は、例外タイプによって異なります。各タイプの例外からの復帰方法については、P. 5-7「復帰アドレスと復帰命令」を参照して下さい。

注注注注

リセットハンドラはメインコードを直接実行するため、リセットハンドラから復帰する必要はありません。

例外ハンドラのエントリコードが、スタックを使用して例外処理中も保存しておかなければならないレジスタをストアする場合には、̂ 修飾子を付けた多重ロード命令を使

用してこれに復帰することができます。例えば、例外ハンドラが以下をスタックに保存する場合:

• ハンドラが呼び出されたときに使用されていた全ての作業レジスタ

• データ処理命令と同じ効果を出すように修正したリンクレジスタ

この例外ハンドラからは以下を使用して 1つの命令で復帰することができます。

LDMFD sp!,{r0-r12,pc}^

^修飾子は、CPSRを SPSR から復元することを指定します。この修飾子は、特権モードから使用する必要があります。スタック操作の詳細については、ADS アセンブラガイドの「LDMと STMを使用したスタックの実装」を参照して下さい。

Page 95: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

プロセッサ例外処理

ARM DUI0056DJ-00 Copyright © 1999-2001 ARM Limited. All rights reserved. 5-7

5.2.3 復帰アドレスと復帰命令復帰アドレスと復帰命令復帰アドレスと復帰命令復帰アドレスと復帰命令

例外発生時にプログラムカウンタが指す実際の位置は、例外タイプによって異なります。復帰アドレスは、必ずしもプログラムカウンタが指す次の命令であるとは限りません。このセクションでは、各タイプの例外を処理するコードから正しく復帰するための命令について説明します。

注注注注

例外が Thumb状態で発生したときの、Thumb対応プロセッサでの復帰アドレスについては、P. 5-42「復帰アドレス」を参照して下さい。

SWIハンドラおよび未定義命令ハンドラからの復帰ハンドラおよび未定義命令ハンドラからの復帰ハンドラおよび未定義命令ハンドラからの復帰ハンドラおよび未定義命令ハンドラからの復帰

SWI 例外と未定義命令例外は、命令自身によって生成されるため、プログラムカウンタはこれらの例外が発生しても更新されません。プロセッサは (pc - 4)を lr_ modeにストアします。これにより、lr_modeは次に実行される命令を指します。以下を使用してlrからプログラムカウンタを復元すると、

MOVS pc, lr

ハンドラから制御が戻されます。

以下は、復帰アドレスをスタックし、復帰時にそれをポップするハンドラエントリ /イグジットコードを示しています。

STMFD sp!,{reglist,lr} ;... LDMFD sp!,{reglist,pc}^

FIQハンドラおよびハンドラおよびハンドラおよびハンドラおよび IRQハンドラからの復帰ハンドラからの復帰ハンドラからの復帰ハンドラからの復帰

1つの命令の実行を後えるたびに、プロセッサは割り込みピンが LOWになっているかどうかと、CPSR 内の割り込みディセーブルビットがクリアされているかどうかをチェックします。この結果、プログラムカウンタが更新されている場合にのみ IRQ 例外または FIQ 例外が生成されます。プロセッサは (pc - 4) を lr_mode にストアします。これにより lr_modeは、例外が発生した命令の終わりから 1つ先の命令を指します。ハンドラが完了したら、実行は lr_modeが指す命令の前の命令から継続する必要があります。実行が再開されるアドレスは、lr_mode 内のアドレスよりも 1 ワード(4 バイト)少ないアドレスとなるため、復帰アドレスは以下のようになります。

SUBS pc, lr, #4

以下は、復帰アドレスをスタックし、復帰時にそれをポップするハンドラエントリ /イグジットコードを示しています。

Page 96: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

プロセッサ例外処理

5-8 Copyright © 1999-2001 ARM Limited. All rights reserved. ARM DUI0056DJ-00

SUB lr,lr,#4 STMFD sp!,{reglist,lr} ;... LDMFD sp!,{reglist,pc}^

プリフェッチアボートハンドラからの復帰プリフェッチアボートハンドラからの復帰プリフェッチアボートハンドラからの復帰プリフェッチアボートハンドラからの復帰

プロセッサが不正アドレスから命令をフェッチしようとすると、その命令に無効のフラグが立てられます。パイプラインに既に入っている命令の実行は、その無効な命令に到達するまで継続され、無効な命令に到達した時点でプリフェッチアボートが生成されます。

この例外ハンドラは、マップされていない命令を物理メモリにロードし、MMUがあればこれを使用して、その仮想メモリ位置を物理メモリ位置にマップします。次にこのハンドラは、プリフェッチアボート例外を発生させた命令の再試行に戻る必要があります。この命令はこの時点でロードして実行します。

プリフェッチアボートの生成時にはプログラムカウンタが更新されていないため、lr_ABTはこの例外を発生させた命令の次の命令を指します。このハンドラは以下を使

用して lr_ABT - 4に戻す必要があります。

SUBS pc,lr, #4

以下は、復帰アドレスをスタックし、復帰時にそれをポップするハンドラエントリ /イグジットコードを示しています。

SUB lr,lr,#4 STMFD sp!,{reglist,lr} ;... LDMFD sp!,{reglist,pc}^

データアボートハンドラからの復帰データアボートハンドラからの復帰データアボートハンドラからの復帰データアボートハンドラからの復帰

ロード命令またはストア命令がメモリへのアクセスを試行すると、プログラムカウンタが更新されます。lr_ABTにストアされる (pc - 4)の値は、例外が発生したアドレスから 2つ先の命令を指します。MMUが存在するときに、これによって適切なアドレスが物理メモリにマップされた場合には、アボートされた命令の実行を再試行できるように、データアボートハンドラはこのアボートされた元の命令に戻る必要があります。したがって復帰アドレスは lr_ABTの値よりも 2ワード(8バイト)少ない値となり、このことから以下の復帰命令が導出されます。

SUBS pc, lr, #8

以下は、復帰アドレスをスタックし、復帰時にそれをポップするハンドラエントリ /イグジットコードを示しています。

SUB lr,lr,#8 STMFD sp!,{reglist,lr} ;... LDMFD sp!,{reglist,pc}^

Page 97: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

プロセッサ例外処理

ARM DUI0056DJ-00 Copyright © 1999-2001 ARM Limited. All rights reserved. 5-9

5.3 例外ハンドラのインストール例外ハンドラのインストール例外ハンドラのインストール例外ハンドラのインストール

新しい例外ハンドラはベクタテーブルにインストールする必要があります。インストールが完了したら、その新しいハンドラは対応する例外が発生するたびに実行されます。

例外ハンドラは以下の 2つの方法でインストールすることができます。

分岐命令分岐命令分岐命令分岐命令 例外ハンドラへの到達に使用できる最も簡単な方法です。ベクタテーブル内の各エントリは、要求されるハンドラルーチンへの分岐を保持します。しかし、この方法には制約があります。分岐命令の範囲は pcに相対して 32MBの範囲内に限定されるため、メモリ構成によっては分岐でハンドラに到達することが不可能な場合があります。

ロードロードロードロード pc命令命令命令命令

この方法では、以下によってプログラムカウンタが直接ハンドラアドレスを指します。

1. ハンドラの絶対アドレスを適切なメモリ位置(ベクタアドレスから 4KB以内)にストアします。

2. 選択されたメモリ位置の内容をプログラムカウンタにロードする命令をベクタ内に配置します。

5.3.1 リセット時のハンドラのインストールリセット時のハンドラのインストールリセット時のハンドラのインストールリセット時のハンドラのインストール

アプリケーションがプログラムの実行開始をデバッガまたはデバッグモニタに依存していない場合には、アセンブリ言語のリセット(または起動)コードからベクタテーブルを直接ロードすることができます。

ROMがメモリ内の 0x0に配置されている場合は、単純にコードの開始部分で各ベクタ

の分岐ステートメントを記述することができます。FIQハンドラが 0x1Cから直接実行

される場合には、この方法で FIQハンドラをインクルードできる場合もあります(P. 5-23「割り込みハンドラ」参照)。

例 5-1 は、ベクタがアドレス 0 の ROM に配置されている場合に、これらのベクタをセットアップするコードを示しています。ロード命令の代わりに分岐ステートメントを使用することができます。

例例例例 5-1

Vector_Init_Block LDR PC, Reset_Addr LDR PC, Undefined_Addr LDR PC, SWI_Addr LDR PC, Prefetch_Addr LDR PC, Abort_Addr NOP ;Reserved vector

Page 98: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

プロセッサ例外処理

5-10 Copyright © 1999-2001 ARM Limited. All rights reserved. ARM DUI0056DJ-00

LDR PC, IRQ_Addr LDR PC, FIQ_Addr

Reset_Addr DCD Start_BootUndefined_Addr DCD Undefined_HandlerSWI_Addr DCD SWI_HandlerPrefetch_Addr DCD Prefetch_HandlerAbort_Addr DCD Abort_Handler DCD 0 ;Reserved vectorIRQ_Addr DCD IRQ_HandlerFIQ_Addr DCD FIQ_Handler

リセット時には 0x0に ROMがくるようにする必要があります。作成したリセットコードで、RAM を 0x0 に再マップすることができます。この再マップを行う前に、その

コードで ROM 内のエリアからベクタ(および必要に応じて FIQ ハンドラ)をコピーし、RAMに配置する必要があります。

この場合は、LDR pc命令を使用してリセットハンドラをアドレス指定する必要がある

ため、リセットベクタコードは位置独立コードにできます。

例 5-2では、P. 5-9例 5-1のベクタを RAM内のベクタテーブルにコピーします。

例例例例 5-2

MOV r8, #0 ADR r9, Vector_Init_Block LDMIA r9!,{r0-r7} ;Copy the vectors (8 words) STMIA r8!,{r0-r7} LDMIA r9!,{r0-r7} ;Copy the DCD'ed addresses STMIA r8!,{r0-r7} ;(8 words again)

別の方法としては、分散ローディング機能を使用して、ベクタテーブルのロード /実行アドレスを定義することもできます。この場合は、Cライブラリがベクタテーブルを自動的にコピーします(第 6章「ROMコードの記述」参照)。

Page 99: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

プロセッサ例外処理

ARM DUI0056DJ-00 Copyright © 1999-2001 ARM Limited. All rights reserved. 5-11

5.3.2 Cからのハンドラのインストールからのハンドラのインストールからのハンドラのインストールからのハンドラのインストール

開発過程においては、例外ハンドラをメインアプリケーションから直接ベクタにインストールしなければならない場合があります。このような場合には、必要とされる命令エンコーディングを適切なベクタアドレスに記述しなければなりません。この作業は、ハンドラへの到達に使用する分岐方式とロード pc方式のどちらでも行うことができます。

分岐方式分岐方式分岐方式分岐方式

必要な命令は以下のように構成することができます。

1. 例外ハンドラのアドレスを取得します。

2. そのアドレスから、対応するベクタのアドレスを引きます。

3. プリフェッチ分を見越して 0x8を引きます。

4. バイトオフセットではなくワードオフセットになるように、上記の結果を 2だけ右にシフトします。

5. この結果の上位 8 ビットがクリアされ、結果が 24 ビット長しかないことを確認します(分岐のオフセットがこの長さに制限されているため)。

6. この結果と 0xEA000000(分岐命令のオペコード)の論理 ORを取り、ベクタに配置する値を求めます。

P. 5-12例 5-3は、このアルゴリズムを実装する C関数を示しています。この C関数は以下の引数を取ります。

• ハンドラのアドレス

• ハンドラをインストールする先のベクタのアドレス

この関数でハンドラをインストールし、ベクタの元の内容を戻すことができます。この結果は、特定の例外に使用されるハンドラのチェインを作成するときに使用できます。詳細については、P. 5-38「例外ハンドラのチェインニング」を参照して下さい。

Page 100: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

プロセッサ例外処理

5-12 Copyright © 1999-2001 ARM Limited. All rights reserved. ARM DUI0056DJ-00

例例例例 5-3

unsigned Install_Handler (unsigned *handlerloc, unsigned *vector)/* Updates contents of 'vector' to contain LDR pc,,[pc,#offset] *//* instruction to cause long branch to address in handlerloc *//* Function return value is original contents of 'vector'.*/

{ unsigned vec, oldvec; vec = *handlerloc - (unsigned)vector - 0x8; if ((vec & 0xFFFFF000) != 0) { /* diagnose the fault */ exit (1); } vec = 0xE59FF000 | vec; oldvec = *vector; *vector = vec; return (oldvec);}

以下のコードはこれを呼び出して IRQハンドラをインストールします。

unsigned *irqvec = (unsigned *)0x18;Install_Handler ((unsigned)IRQHandler, irqvec);

この場合、戻された IRQベクタの元の内容は破棄されます。

ロードロードロードロード pc方式方式方式方式

必要な命令は以下のように構成することができます。

1. 例外ハンドラのアドレスを含むワードのアドレスを取得します。

2. そのアドレスから、対応するベクタのアドレスを引きます。

3. プリフェッチ分を見越して 0x8を引きます。

4. 結果が 12ビットで表現されていることを確認します。

5. この結果と 0xe59FF000(LDR pc, [pc,#offset]のオペコード)の論理 ORを取り、ベクタに配置する値を求めます。

6. このハンドラのアドレスを記憶位置に配置します。

P. 5-13例 5-4は、この方式をを実装する Cルーチンを示しています。

Page 101: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

プロセッサ例外処理

ARM DUI0056DJ-00 Copyright © 1999-2001 ARM Limited. All rights reserved. 5-13

例例例例 5-4

unsigned Install_Handler (unsigned location, unsigned *vector)

/* Updates contents of 'vector' to contain LDR pc, [pc, #offset] *//* instruction to cause long branch to address in `location'. *//* Function return value is original contents of 'vector'. */

{ unsigned vec, oldvec; vec = ((unsigned)location - (unsigned)vector - 0x8) | 0xe59ff000 oldvec = *vector; *vector = vec; return (oldvec);}

以下のコードはこれを呼び出して IRQハンドラをインストールします。

unsigned *irqvec = (unsigned *)0x18;static unsigned pIRQ_Handler = (unsigned)IRQ_handlerInstall_Handler (&pIRQHandler, irqvec);

この例でも、戻される元の IRQ ベクタの内容は破棄されますが、この内容を使用してハンドラのチェインを作成できる場合があります。詳細については、P. 5-38「例外ハンドラのチェインニング」を参照して下さい。

注注注注

StrongARM®や ARM940Tなど、命令キャッシュとデータキャッシュが分かれているプロセッサを使用している場合は、キャッシュコヒーレンシ問題がベクタの新しい内容を使用するときの妨げにならないように注意する必要があります。

データキャッシュ(または少なくとも修正ベクタを含むエントリ)は、新しいベクタの内容をメインメモリに書き込めるように、クリーンする必要があります。次に、新しいベクタの内容をメインメモリから読み出せるように、命令キャッシュをフラッシュする必要があります。

キャッシュのクリーン操作とフラッシュ操作については、ターゲットプロセッサのテクニカルリファレンスマニュアルを参照して下さい。

Page 102: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

プロセッサ例外処理

5-14 Copyright © 1999-2001 ARM Limited. All rights reserved. ARM DUI0056DJ-00

5.4 SWIハンドラハンドラハンドラハンドラ

SWIハンドラに入るとき、このハンドラはどの SWIが呼び出されているかを確定する必要があります。この情報は命令自身のビット 0~ 23にストアするか、通常は r0~ r3のいずれかとなる、1つの整数レジスタに渡すことができます(図 5-1参照)。

図図図図 5-1 ARM SWI命令命令命令命令

トップレベル SWIハンドラは、リンクレジスタに相対する SWI命令をロードすることができます(LDR swi, [lr, #-4])。このロードは、アセンブリ言語か、C/C++インラインアセンブラで行います。

SWIハンドラは、まず最初に例外を発生させたSWI命令をレジスタにロードする必要が

あります。この時点で lr_SVCはその SWI命令のアドレスを保持するため、この SWI

は以下を使用してレジスタにロードします。

LDR r0, [lr,#-4]

SWI ハンドラは次にコメントフィールドビットを検査し、要求されている動作を決定します。SWI 番号は、オペコードの上位 8 ビットをクリアすることによって抽出されます。

BIC r0, r0, #0xFF000000

例 5-5 は、これらの命令を組み合わせてトップレベル SWI ハンドラを形成する方法を示しています。

ARM状態と Thumb状態の両方の SWI命令を処理するハンドラのサンプルについては、

P. 5-43「プロセッサ状態の決定」を参照して下さい。

例例例例 5-5

AREA TopLevelSwi, CODE, READONLY ; Name this block of code. EXPORT SWI_HandlerSWI_Handler STMFD sp!,{r0-r12,lr} ; Store registers. LDR r0,[lr,#-4] ; Calculate address of SWI instruction and load it into r0. BIC r0,r0,#0xff000000 ; Mask off top 8 bits of instruction to give SWI number. ; ; Use value in r0 to determine which SWI routine to execute. ; LDMFD sp!, {r0-r12,pc}^ ; Restore registers and return. END ; Mark end of this file.

Page 103: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

プロセッサ例外処理

ARM DUI0056DJ-00 Copyright © 1999-2001 ARM Limited. All rights reserved. 5-15

5.4.1 アセンブリ言語を使用したアセンブリ言語を使用したアセンブリ言語を使用したアセンブリ言語を使用した SWIハンドラハンドラハンドラハンドラ

要求された SWI番号のハンドラを呼び出す最も簡単な方法は、ジャンプテーブルを使用する方法です。r0が SWI番号を保持しているとき、例 5-6のコードは P. 5-14例 5-5のトップレベルハンドラの BIC命令の次から挿入することができます。

例例例例 5-6 SWIジャンプテーブルジャンプテーブルジャンプテーブルジャンプテーブル

CMP r0,#MaxSWI ; Range check LDRLS pc, [pc,r0,LSL #2] B SWIOutOfRangeSWIJumpTable DCD SWInum0 DCD SWInum1 ; DCD for each of other SWI routinesSWInum0 ; SWI number 0 code B EndofSWISWInum1 ; SWI number 1 code B EndofSWI ; Rest of SWI handling code ;EndofSWI ; Return execution to top level ; SWI handler so as to restore ; registers and return to program.

5.4.2 Cおよびアセンブリ言語を使用したおよびアセンブリ言語を使用したおよびアセンブリ言語を使用したおよびアセンブリ言語を使用した SWIハンドラハンドラハンドラハンドラ

トップレベルハンドラは常に ARM アセンブリ言語で記述する必要がありますが、各

SWI を処理するルーチンはアセンブリ言語でも C でも記述できます。この点に関する制約条件については、P. 5-18「スーパバイザモードでの SWIの使用」を参照して下さい。

トップレベルハンドラでは BL(リンク付き分岐)命令を使用して適切な C関数にジャンプします。SWI番号はアセンブリルーチンによって r0にロードされるため、この番号は最初のパラメータとして C関数に渡されます(ARMプロシージャコール標準に基づく)。C関数はこの値を switch()ステートメントなどで使用することができます。

P. 5-14例 5-5の SWI_Handlerルーチンには、以下の行を追加することができます。

BL C_SWI_Handler ; Call C routine to handle the SWI

P. 5-16例 5-7は、この C関数の実装方法を示しています。

Page 104: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

プロセッサ例外処理

5-16 Copyright © 1999-2001 ARM Limited. All rights reserved. ARM DUI0056DJ-00

例例例例 5-7

void C_SWI_handler (unsigned number){ switch (number) {case 0 : /* SWI number 0 code */ break; case 1 : /* SWI number 1 code */ break; : : default : /* Unknown SWI - report error */ }}

スーパバイザスタック空間は限られているため、大量のスタック空間を必要とする関数の使用は避けて下さい。

C で記述した SWI ハンドラとの間で値を受け渡すことはできますが、トップレベルハンドラはスタックポインタの値を(r1内の)第 2パラメータとして C関数に渡します。

MOV r1, sp ; Second parameter to C routine... ; ...is pointer to register values. BL C_SWI_Handler ; Call C routine to handle the SWI

この C関数はレジスタの値にアクセスできるように以下のように更新されます。

void C_SWI_handler(unsigned number, unsigned *reg)

これでこの C 関数は、SWI 命令がメインアプリケーションコードで検出されたときにレジスタに保持されている値にアクセスできます(P. 5-17図 5-2参照)。値はレジスタから以下のように読み出し、

value_in_reg_0 = reg [0]; value_in_reg_1 = reg [1]; value_in_reg_2 = reg [2]; value_in_reg_3 = reg [3];

以下のようにライトバックします。

reg [0] = updated_value_0; reg [1] = updated_value_1; reg [2] = updated_value_2; reg [3] = updated_value_3;

これにより、更新された値が適切なスタック位置に書き込まれ、トップレベルハンドラによってレジスタに復元されます。

Page 105: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

プロセッサ例外処理

ARM DUI0056DJ-00 Copyright © 1999-2001 ARM Limited. All rights reserved. 5-17

図図図図 5-2 スーパバイザスタックへのアクセススーパバイザスタックへのアクセススーパバイザスタックへのアクセススーパバイザスタックへのアクセス

Page 106: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

プロセッサ例外処理

5-18 Copyright © 1999-2001 ARM Limited. All rights reserved. ARM DUI0056DJ-00

5.4.3 スーパバイザモードでのスーパバイザモードでのスーパバイザモードでのスーパバイザモードでの SWIの使用の使用の使用の使用

SWI命令が実行されるとき:

1. プロセッサがスーパバイザモードに入ります。

2. CPSRが spsr_SVCにストアされます。

3. 復帰アドレスが lr_SVC にストアされます(P. 5-5「例外に対するプロセッサの応答」参照)。

プロセッサが既にスーパバイザモードにあるときは、lr_SVC と spsr_SVC が更新さ

れます。

スーパバイザモードで SWI を呼び出す場合は、リンクレジスタと SPSR の元の値が失われないように、lr_SVCおよび spsr_SVCをストアする必要があります。例えば、特

定の SWI番号のハンドラルーチンが別の SWIを呼び出す場合は、そのハンドラルーチンに lr_SVCと spsr_SVCの両方をスタックにストアさせる必要があります。このよ

うにハンドラの各呼び出しに、ハンドラを呼び出した SWIに続く命令に復帰するために必要な情報を確実に保存させます。例 5-8は、この様子を示しています。

例例例例 5-8 SWIハンドラハンドラハンドラハンドラ

STMFD sp!,{r0-r3,r12,lr} ; Store registers. MOV r1, sp ; Set pointer to parameters. MRS r0, spsr ; Get spsr. STMFD sp!, {r0} ; Store spsr onto stack. This is only really needed in case of ; nested SWIs.

; the next two instructions only work for SWI calls from ARM state. ; See P. 5-30ó·5-17 for a version that works for calls from either ARM or Thumb.

LDR r0,[lr,#-4] ; Calculate address of SWI instruction and load it into r0. BIC r0,r0,#0xFF000000 ; Mask off top 8 bits of instruction to give SWI number.

; r0 now contains SWI number ; r1 now contains pointer to stacked registers

BL C_SWI_Handler ; Call C routine to handle the SWI. LDMFD sp!, {r0} ; Get spsr from stack. MSR spsr_cf, r0 ; Restore spsr. LDMFD sp!, {r0-r3,r12,pc}^ ; Restore registers and return.

C/C++による入れ子による入れ子による入れ子による入れ子 SWIの記述の記述の記述の記述

入れ子 SWIを Cまたは C++で記述することができます。ARMコンパイラによって生成されるコードは、必要に応じて lr_SVCのストアと再ロードを実行します。

Page 107: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

プロセッサ例外処理

ARM DUI0056DJ-00 Copyright © 1999-2001 ARM Limited. All rights reserved. 5-19

5.4.4 アプリケーションからのアプリケーションからのアプリケーションからのアプリケーションからの SWIの呼び出しの呼び出しの呼び出しの呼び出し

SWIはアセンブリ言語または C/C++から呼び出すことができます。

アセンブリ言語では、必要なレジスタ値を設定して関連 SWIを発行します。例:

MOV r0, #65 ; load r0 with the value 65 SWI 0x0 ; Call SWI 0x0 with parameter value in r0

この SWI 命令は、ほぼ全ての ARM 命令と同じように、条件付きで実行することができます。

C/C++からは SWIを __SWI関数として宣言し、これを呼び出します。例:

__swi(0) void my_swi(int); . . . my_swi(65);

これにより、呼び出しのオーバヘッドを発生させることなく SWIをインラインでコンパイルすることができますが、以下の条件があります。

• どの引数も r0~ r3だけに渡される。

• どの結果も r0~ r3だけに返される。

SWIが実際の関数呼び出しであるかのように、パラメータが SWIに渡されます。しかし、2~ 4個のリターン値がある場合には、それらのリターン値が構造で返されることをコンパイラに通知する必要があり、__value_in_regs ディレクティブを使用しま

す。これは構造の値を返す関数が、得られた構造を配置するアドレスを最初の引数として使用する void関数であるかのように処理されるのが一般的であるためです。

例 5-9および P. 5-20例 5-10は、SWI番号 0x0、0x1、0x2、0x3の SWIハンドラを示しています。SWI 0x0および 0x1は、それぞれ 2つの整数パラメータを使用し、1つの結果を返します。SWI 0x2 は 4 つのパラメータを使用し、1 つの結果を返します。SWI 0x3は 4つのパラメータを使用し、4つの結果を返します。このサンプルはExamples\SWI\main.cと Examples\SWI\swi.hに収録されています。

例例例例 5-9 main.c

#include <stdio.h>#include "swi.h"

unsigned *swi_vec = (unsigned *)0x08;extern void SWI_Handler(void);

int main( void ){

Page 108: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

プロセッサ例外処理

5-20 Copyright © 1999-2001 ARM Limited. All rights reserved. ARM DUI0056DJ-00

int result1, result2; struct four_results res_3; Install_Handler( (unsigned) SWI_Handler, swi_vec ); printf("result1 = multiply_two(2,4) = %d\n", result1 = multiply_two(2,4)); printf("result2 = multiply_two(3,6) = %d\n", result2 = multiply_two(3,6)); printf("add_two( result1, result2 ) = %d\n", add_two( result1, result2 )); printf("add_multiply_two(2,4,3,6) = %d\n", add_multiply_two(2,4,3,6)); res_3 = many_operations( 12, 4, 3, 1 ); printf("res_3.a = %d\n", res_3.a ); printf("res_3.b = %d\n", res_3.b ); printf("res_3.c = %d\n", res_3.c ); printf("res_3.d = %d\n", res_3.d ); return 0;}

例例例例 5-10 swi.h

__swi(0) int multiply_two(int, int);__swi(1) int add_two(int, int);__swi(2) int add_multiply_two(int, int, int, int);

struct four_results{ int a; int b; int c; int d;};

__swi(3) __value_in_regs struct four_results many_operations(int, int, int, int);

5.4.5 アプリケーションからの動的なアプリケーションからの動的なアプリケーションからの動的なアプリケーションからの動的な SWIの呼び出しの呼び出しの呼び出しの呼び出し

状況によっては、SWI番号がランタイムまで分からない SWIを呼び出さなければならない場合があります。このような状況は、例えば 1 つのオブジェクトに対して実行可能な複数の関連命令があり、命令ごとに SWI があるような場合に発生し得ます。このような場合には、前述の方法は適切ではありません。

この状況には、以下のような方法で対処することができます。

• SWI番号から SWI命令を構成し、それをどこかにストアした後で実行する。

Page 109: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

プロセッサ例外処理

ARM DUI0056DJ-00 Copyright © 1999-2001 ARM Limited. All rights reserved. 5-21

• それ自身の引数に対して実行される実演算コードを別の引数として取る汎用SWIを使用する。この汎用 SWIが命令をデコードして実行します。

2番目の方法は、要求する演算の値をレジスタに、一般的には r0または r12に渡すことにより、アセンブリ言語で実装することが可能です。これで SWIハンドラが適切なレジスタ内の値に作用するように書き直すことができます。場合によっては値を SWIのコメントフィールドに渡す必要があるため、これらの 2 つの方法を組み合わせて使用することも考えられます。

例えば、オペレーティングシステムが 1つの SWI命令しか使用せず、レジスタを使用

して要求する演算の値を渡すとします。この場合は残りの SWI空間をアプリケーション固有の SWI に使用することができます。この方法は、特定のアプリケーションで、命令からの SWI番号の抽出にかかるオーバヘッドが大きすぎる場合に使用することができます。これが ARM(0x123456)および Thumb(0xAB)のセミホステッド SWI

の実装方法です。

例 5-11は、C関数呼び出しをセミホスティング SWI にマップするときの __swi の使

用方法を示しています。このサンプルは Examples\embedded\embed\retarget.c

に収録されています。

例例例例 5-11 C関数のセミホスティング関数のセミホスティング関数のセミホスティング関数のセミホスティング SWIへのマッピングへのマッピングへのマッピングへのマッピング

#ifdef __thumb/* Thumb Semihosting SWI */#define SemiSWI 0xAB#else/* ARM Semihosting SWI */#define SemiSWI 0x123456#endif

/* Semihosting SWI to write a character */ __swi(SemiSWI) void Semihosting(unsigned op, char *c);#define WriteC(c) Semihosting (0x3,c)

void write_a_character(int ch){

char tempch = ch; WriteC( &tempch );

}

コンパイラには、r12を使用した要求する演算の値の受け渡しをサポートするためのメカニズムが組み込まれています。ARMプロシージャコール標準では r12は ipレジスタであり、関数呼び出しの間だけ特定の役割が与えられます。その他の場合は、このレジスタをスクラッチレジスタとして使用できます。汎用 SWIへの引数はレジスタ r0~

Page 110: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

プロセッサ例外処理

5-22 Copyright © 1999-2001 ARM Limited. All rights reserved. ARM DUI0056DJ-00

r3に渡し、それらの値は前述のとおり任意に r0~ r3に返します。r12に渡す演算の値は、汎用 SWIに呼び出される SWIの番号にすることもできますが、必ずしもそうである必要はありません。

例 5-12は、汎用、つまり間接 SWIを使用する Cフラグメントを示しています。

例例例例 5-12

__swi_indirect(0x80) unsigned SWI_ManipulateObject(unsigned operationNumber, unsigned object,unsigned parameter);

unsigned DoSelectedManipulation(unsigned object, unsigned parameter, unsigned operation){ return SWI_ManipulateObject(operation, object, parameter);}

これにより、以下のコードが生成されます。

DoSelectedManipulation PROC STMFD sp!,{r3,lr} MOV r12,r2 SWI 0x80 LDMFD sp!,{r3,pc} ENDP

また、__swi方式を使用して、SWI番号を Cから r0に渡すことも可能です。例えば、SWI 0x0を汎用 SWIとして使用し、演算 0が文字の読み出し、演算 1が文字の書き込みであるときは、以下のように設定することができます。

__swi (0) char __ReadCharacter (unsigned op);__swi (0) void __WriteCharacter (unsigned op, char c);

上記は、以下を定義すると分かりやすくなります。

#define ReadCharacter () __ReadCharacter (0);#define WriteCharacter (c) __WriteCharacter (1, c);

しかし、r0 をこの方法で使用した場合には、SWI にパラメータを渡すレジスタには 3つのレジスタしか使用できません。通常、r0~ r3よりも多くのパラメータをサブルーチンに渡す必要がある場合には、スタックを使用します。しかしながら、スタックに格納されるパラメータは、SWI ハンドラに使用されるスーパバイザスタックではなくユーザモードスタックに格納されるのが一般的であるため、SWI ハンドラからはアクセスしにくくなります。

別の方法としては、レジスタの 1つ(通常、r1)を使用して、他のパラメータを保存しているメモリブロックを指すことができます。

Page 111: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

プロセッサ例外処理

ARM DUI0056DJ-00 Copyright © 1999-2001 ARM Limited. All rights reserved. 5-23

5.5 割り込みハンドラ割り込みハンドラ割り込みハンドラ割り込みハンドラ

ARMプロセッサには FIQと IRQの 2つのレベルの外部割り込みがあり、両方ともコアへのレベル感知式 LOW アクティブシグナルです。割り込みを発生させるには、CPSR内の適切なディセーブルビットをクリアしておく必要があります。

FIQは、以下の 2通りの方法で IRQよりも優先されます。

• 複数の割り込みが発生すると、FIQが最初に処理される。

• FIQの処理によって IRQがディセーブルされ、FIQハンドラが IRQを再イネーブルするまで、IRQの処理が阻止される。IRQは、ハンドラの終わりで SPSRからCPSRを復元することによって再イネーブルするのが一般的です。

FIQベクタはベクタテーブルの最後のエントリ(アドレス 0x1C)であるため、FIQハンドラをこのベクタ位置に直接配置して、そのアドレスからシーケンシャルに実行することができます。したがって分岐とそれに関連する遅延を考慮する必要がなく、システムにキャッシュが搭載されていれば、ベクタテーブルと FIQ ハンドラの全てをキャッシュ内の 1 つのブロックにロックしておくことができます。これが重要な意味をもつのは、FIQ ができるだけ速く割り込みを処理する目的で設計されているからです。さらに FIQ モードの 5 つのバンクレジスタのイネーブルステータスをハンドラへの呼び出し間で保持することによって、実行速度を上げることができます。

注注注注

割り込みハンドラには、割り込みソースをクリアするコードを含める必要があります。

Page 112: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

プロセッサ例外処理

5-24 Copyright © 1999-2001 ARM Limited. All rights reserved. ARM DUI0056DJ-00

5.5.1 Cを使用した単純な割り込みハンドラの記述を使用した単純な割り込みハンドラの記述を使用した単純な割り込みハンドラの記述を使用した単純な割り込みハンドラの記述

__irq関数宣言キーワードを使用して、単純な C割り込みハンドラを記述することができます。__irq キーワードは、単純な 1 レベルの割り込みハンドラと、サブルーチンを呼び出す割り込みハンドラの両方に使用できます。ただし、__irq キーワードを

使用しても SPSRの保存と復元は発生しないため、これをリエントラント割り込みハンドラに使用することはできません。ここでのリエントラントとは、ハンドラが割り込みを再イネーブルし、それ自身に割り込ませることが可能なことを意味します。詳細については、P. 5-26「リエントラント割り込みハンドラ」を参照して下さい。

__irqキーワードを使用すると:

• 全ての ATPCS更新可能レジスタが保存される。

• 当該関数によって使用される他の全てのレジスタ(浮動小数点レジスタを除く)が保存される。

• プログラムカウンタに (lr - 4)をセットし、CPSRに元の値を復元することによって関数が終了する。

関数呼び出しがサブルーチンの場合、__irq は更新可能レジスタの保存に加え、その

割り込みモードのリンクレジスタも保存します。詳細については、「割り込みハンドラからのサブルーチンの呼び出し」を参照して下さい。

注注注注

tcc を使用する場合は、この方法で C 割り込みハンドラを生成することはできません。tccは Thumbコードしか生成しないため、__irqキーワードは tccによって無効化されます。割り込みその他の例外が発生すると、プロセッサは必ず ARM状態に切り替えられます。

しかし、インターワーキングをイネーブルしておけば、__irq 関数によって呼び出されるサブルーチンは Thumb用にコンパイルすることができます。詳細については、第3章「ARMと Thumbのインターワーキング」を参照して下さい。

割り込みハンドラからのサブルーチンの呼び出し割り込みハンドラからのサブルーチンの呼び出し割り込みハンドラからのサブルーチンの呼び出し割り込みハンドラからのサブルーチンの呼び出し

トップレベル割り込みハンドラからサブルーチンを呼び出す場合に __irqキーワード

を使用すると、SUBS命令が lr_IRQの値を使用して割り込み処理後に正しいアドレス

に復帰できるように、この値も復元されます。

P. 5-25例 5-13は、この様子を示しています。トップレベル割り込みハンドラは、メモリマップ割り込みコントローラのベースアドレスを 0x80000000で読み出します。こ

のアドレスの値が 1 のとき、トップレベルハンドラは C で記述されたハンドラに分岐します。

Page 113: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

プロセッサ例外処理

ARM DUI0056DJ-00 Copyright © 1999-2001 ARM Limited. All rights reserved. 5-25

例例例例 5-13

__irq void IRQHandler (void){ volatile unsigned int *base = (unsigned int *) 0x80000000;

if (*base == 1) // which interrupt was it? { C_int_handler(); // process the interrupt } *(base+1) = 0; // clear the interrupt}

armccでコンパイルすると、例 5-13から以下のコードが生成されます。

IRQHandler PROC STMFD sp!,{r0-r4,r12,lr} MOV r4,#0x80000000 LDR r0,[r4,#0] SUB sp,sp,#4 CMP r0,#1 BLEQ C_int_handler MOV r0,#0 STR r0,[r4,#4] ADD sp,sp,#4 LDMFD sp!,{r0-r4,r12,lr} SUBS pc,lr,#4 ENDP

これを、__irqキーワードを使用していないときの結果と比較して下さい。

IRQHandler PROC STMFD sp!,{r4,lr} MOV r4,#0x80000000 LDR r0,[r4,#0] CMP r0,#1 BLEQ C_int_handler MOV r0,#0 STR r0,[r4,#4] LDMFD sp!,{r4,pc} ENDP

Page 114: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

プロセッサ例外処理

5-26 Copyright © 1999-2001 ARM Limited. All rights reserved. ARM DUI0056DJ-00

5.5.2 リエントラント割り込みハンドラリエントラント割り込みハンドラリエントラント割り込みハンドラリエントラント割り込みハンドラ

注注注注

以下で紹介する方法は、IRQと FIQの両方の割り込みに使用できます。しかし、FIQ割り込みはできるだけ速く処理するべきであり、通常は 1 つの割り込みソースしか存在しないため、リエントリを見越しておく必要はないかもしれません。

割り込みハンドラが割り込みを再イネーブルしてサブルーチンを呼び出し、別の割り込みが発生すると、このサブルーチンの復帰アドレス(lr_IRQに保存される)は 2番目の IRQの発生時に更新されます。Cで __irqキーワードを使用しても、リエントラ

ント割り込みハンドラに必要な SPSRの保存と復元は行われないため、トップレベルハンドラはアセンブリ言語で記述する必要があります。

リエントラント割り込みハンドラは IRQ状態を保存し、プロセッサモードを切り替え、入れ子サブルーチンまたは C 関数に分岐する前に新しいプロセッサモードの状態を保存する必要があります。

ARM アーキテクチャ v4 以上では、システムモードに切り替えることができます。システムモードではユーザモードレジスタが使用され、例外ハンドラに必要となることがある特権アクセスも可能です。詳細については、P. 5-45「システムモード」を参照して下さい。ARMアーキテクチャv4よりも前のアーキテクチャでは、この代わりにスーパバイザモードに切り替える必要があります。

以下のステップに従って、IRQ ハンドラで安全に割り込みを再イネーブルすることができます。

1. 復帰アドレスを構成し、IRQスタックに保存します。

2. 作業レジスタと spsr_IRQを保存します。

3. 割り込みソースをクリアします。

4. システムモードに切り替え、割り込みを再イネーブルします。

5. ユーザモードのリンクレジスタと、非呼び出し先保存レジスタを保存します。

6. C割り込みハンドラ関数を呼び出します。

7. C割り込みハンドラが復帰するとき、ユーザモードレジスタを復元し、割り込みをディセーブルします。

8. IRQモードに切り替え、割り込みをディセーブルします。

9. 作業レジスタと spsr_IRQを復元します。

10. この IRQから復帰します。

P. 5-27例 5-14は、上記の方法をシステムモードで使用したときの様子を示しています。レジスタ r12および r14は、lr_IRQがスタックにプッシュされた後に一時作業レジスタとして使用されます。

Page 115: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

プロセッサ例外処理

ARM DUI0056DJ-00 Copyright © 1999-2001 ARM Limited. All rights reserved. 5-27

例例例例 5-14

AREA INTERRUPT, CODE, READONLY IMPORT C_irq_handlerIRQ SUB lr, lr, #4 ; construct the return address STMFD sp!, {lr} ; and push the adjusted lr_IRQ MRS r14, SPSR ; copy spsr_IRQ to r14 STMFD sp!, {r12, r14} ; save work regs and spsr_IRQ

; Add instructions to clear the interrupt here ; then re-enable interrupts.

MSR CPSR_c, #0x1F ; switch to SYS mode, FIQ and IRQ ; enabled. USR mode registers ; are now current. STMFD sp!, {r0-r3, lr} ; save lr_USR and non-callee ; saved registers BL C_irq_handler ; branch to C IRQ handler. LDMFD sp!, {r0-r3, lr} ; restore registers MSR CPSR_c, #0x92 ; switch to IRQ mode and disable ; IRQs. FIQ is still enabled.

LDMFD sp!, {r12, r14} ; restore work regs and spsr_IRQ MSR SPSR_cf, r14 LDMFD sp!, {pc}^ ; return from IRQ. END

Page 116: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

プロセッサ例外処理

5-28 Copyright © 1999-2001 ARM Limited. All rights reserved. ARM DUI0056DJ-00

5.5.3 アセンブリ言語を使用した割り込みハンドラのサンプルアセンブリ言語を使用した割り込みハンドラのサンプルアセンブリ言語を使用した割り込みハンドラのサンプルアセンブリ言語を使用した割り込みハンドラのサンプル

割り込みハンドラは、できるだけ速く実行できるようにアセンブリ言語で記述するのが一般的です。このセクションではいくつかのサンプルを紹介します。

• シングルチャネル DMA転送

• デュアルチャネル DMA転送:P. 5-29

• 割り込みの優先度の決定:P. 5-30

• コンテキストスイッチ:P. 5-31

シングルチャネルシングルチャネルシングルチャネルシングルチャネル DMA転送転送転送転送

例 5-15は、メモリ転送への割り込み駆動型 I/O(ソフト DMA)を実行する割り込みハンドラを示しています。このコードは FIQ ハンドラです。割り込み間の状態は、バンク付き FIQレジスタを使用して保持します。このコードは、0x1Cに配置するのが最も適しています。

このサンプルコードでは:

r8 データが読み出される I/Oデバイスのベースアドレスを指します。

IOData ベースアドレスから、読み出される 32ビットデータレジスタまでのオフセットです。このレジスタの読み出しによって、割り込みがクリアされます。

r9 データ転送先のメモリ位置を指します。

r10 転送先の最後のアドレスを指します。

通常の転送を処理する全体のシーケンスには 4 命令が使用されます。条件付き復帰の後に位置するコードは、転送が完了したことを通知するために使用されます。

例例例例 5-15

LDR r11, [r8, #IOData] ; Load port data from the IO ; device. STR r11, [r9], #4 ; Store it to memory: update ; the pointer. CMP r9, r10 ; Reached the end ? SUBLSS pc, lr, #4 ; No, so return. ; Insert transfer complete ; code here.

ロード命令をバイトロード命令に置き換えることにより、バイト転送を実行することができます。メモリから I/Oデバイスへの転送は、ロード命令とストア命令の間でアドレシングモードをスワッピングすることによって実行されます。

Page 117: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

プロセッサ例外処理

ARM DUI0056DJ-00 Copyright © 1999-2001 ARM Limited. All rights reserved. 5-29

デュアルチャネルデュアルチャネルデュアルチャネルデュアルチャネル DMA転送転送転送転送

例 5-16は P. 5-28例 5-15と似ていますが、処理されるチャネルが 2つあります。このコードは FIQハンドラです。割り込み間の状態は、バンク付き FIQレジスタを使用して保持します。このコードは、0x1Cに配置するのが最も適しています。

このサンプルコードでは:

r8 データが読み出されるI/Oデバイスのベースアドレスを指します。

IOStat ベースアドレスから、2 つのポートのうちのどちらが割り込みを発生させたかを示すレジスタへのオフセットです。

IOPort1Active 第 1ポートが割り込みを発生させたことを示すビットマスクです(これ以外の場合は、第 2 ポートが割り込みを発生させたとみなされます)。

IOPort1, IOPort2 読み出される 2つのデータレジスタへのオフセットです。データレジスタの読み出しによって、対応するポートの割り込みがクリアされます。

r9 第 1ポートからのデータを転送する先のメモリ位置を指します。

r10 第 2ポートからのデータを転送する先のメモリ位置を指します。

r11, r12 転送先の最後のアドレスを指します(第 1 ポートには r11、第 2ポートには r12が使用されます)。

通常の転送を処理する全体のシーケンスには 9 命令が使用されます。条件付き復帰の後に位置するコードは、転送が完了したことを通知するために使用されます。

例例例例 5-16

LDR r13, [r8, #IOStat] ; Load status register to find which port ; caused the interrupt. TST r13, #IOPort1Active LDREQ r13, [r8, #IOPort1] ; Load port 1 data. LDRNE r13, [r8, #IOPort2] ; Load port 2 data. STREQ r13, [r9], #4 ; Store to buffer 1. STRNE r13, [r10], #4 ; Store to buffer 2. CMP r9, r11 ; Reached the end? CMPLE r10, r12 ; On either channel? SUBNES pc, lr, #4 ; Return ; Insert transfer complete code here.

Page 118: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

プロセッサ例外処理

5-30 Copyright © 1999-2001 ARM Limited. All rights reserved. ARM DUI0056DJ-00

ロード命令をバイトロード命令に置き換えることにより、バイト転送を実行すること

ができます。メモリから I/Oデバイスへの転送は、条件付きロード命令と条件付きストア命令の間でアドレシングモードをスワッピングすることによって実行されます。

割り込みの優先度の決定割り込みの優先度の決定割り込みの優先度の決定割り込みの優先度の決定

例 5-17では、最高 32の割り込みソースを適切なハンドラルーチンにディスパッチします。このサンプルは通常の割り込みベクタ(IRQ)に使用する目的で設計されているため、位置 0x18から分岐させる必要があります。

外部ハードウェアは、割り込みの優先度を決定し、I/O レジスタに優先度の高いアクティブな割り込みを割り当てるために使用します。

このサンプルコードでは:

IntBase 割り込みコントローラのベースアドレスを保持します。

IntLevel 最高優先度のアクティブな割り込みを含むレジスタのオフセットを保持

します。

r13 小さなフル下降スタックを指すとみなされます。

割り込みは、このコードへの分岐も含め、10命令後にイネーブルされます。

各割り込みの特定のハンドラは、さらに 2 命令後に(全てのレジスタをスタックに保存した状態で)開始されます。

また、各ハンドラの最後の 3 命令は割り込みをもう一度オフにした状態で実行されるため、SPSRは安全にスタックから復元することができます。

注注注注

アプリケーションノート 30:"Software Prioritization of Interrupts(ソフトウェアによる割り込み優先度の決定)"では、上記のハードウェアを使用する方法ではなく、ソフトウェアを使用して割り込みの複数ソースの優先度を決定する方法について説明してい

ます。

例例例例 5-17

; first save the critical state SUB lr, lr, #4 ; Adjust the return address ; before we save it. STMFD sp!, {lr} ; Stack return address MRS r14, SPSR ; get the SPSR ... STMFD sp!, {r12, r14} ; ... and stack that plus a ; working register too.

Page 119: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

プロセッサ例外処理

ARM DUI0056DJ-00 Copyright © 1999-2001 ARM Limited. All rights reserved. 5-31

; Now get the priority level of the ; highest priority active interrupt. MOV r12, #IntBase ; Get the interrupt controller's ; base address. LDR r12, [r12, #IntLevel] ; Get the interrupt level (0 to 31).

; Now read-modify-write the CPSR to enable interrupts.

MRS r14, CPSR ; Read the status register. BIC r14, r14, #0x80 ; Clear the I bit ; (use 0x40 for the F bit). MSR CPSR_c, r14 ; Write it back to re-enable ; interrupts and LDR PC, [PC, r12, LSL #2] ; jump to the correct handler. ; PC base address points to this ; instruction + 8 NOP ; pad so the PC indexes this table.

; Table of handler start addresses DCD Priority0Handler DCD Priority1Handler DCD Priority2Handler; ... Priority0Handler STMFD sp!, {r0 - r11} ; Save other working registers. ; Insert handler code here.; ... LDMFD sp!, {r0 - r11} ; Restore working registers (not r12).

; Now read-modify-write the CPSR to disable interrupts. MRS r12, CPSR ; Read the status register. ORR r12, r12, #0x80 ; Set the I bit ; (use 0x40 for the F bit). MSR CPSR_c, r12 ; Write it back to disable interrupts.

; Now that interrupt disabled, can safely restore SPSR then return. LDMFD sp!, {r12, r14} ; Restore r12 and get SPSR. MSR SPSR_csxf, r14 ; Restore status register from r14. LDMFD sp!, {pc}^ ; Return from handler.Priority1Handler; ...

コンテキストスイッチコンテキストスイッチコンテキストスイッチコンテキストスイッチ

P. 5-32例 5-18では、ユーザモードプロセスでコンテキストスイッチを実行します。このコードは、実行準備が整ったプロセッサのプロセス制御ブロック(PCB)を指すポインタリストに基づいて構成されています。

Page 120: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

プロセッサ例外処理

5-32 Copyright © 1999-2001 ARM Limited. All rights reserved. ARM DUI0056DJ-00

図 5-3は、このサンプルで予想している PCBのレイアウトを示しています。

図図図図 5-3 PCBレイアウトレイアウトレイアウトレイアウト

r12 は次に実行するプロセスの PCB へのポインタを指し、このリストの終わりにはゼロポインタが配置されます。レジスタ r13は PCB へのポインタであり、タイムスライス間で保存されるため、エントリでは現在実行中のプロセスの PCBを指します。

例例例例 5-18

STMIA r13, {r0 - r14}^ ; Dump user registers above r13. MRS r0, SPSR ; Pick up the user status STMDB r13, {r0, lr} ; and dump with return address below. LDR r13, [r12], #4 ; Load next process info pointer. CMP r13, #0 ; If it is zero, it is invalid LDMNEDB r13, {r0, lr} ; Pick up status and return address. MSRNE SPSR_cxsf, r0 ; Restore the status. LDMNEIA r13, {r0 - r14}^ ; Get the rest of the registers NOP SUBNES pc, lr, #4 ; and return and restore CPSR. ; Insert "no next process code" here.

Page 121: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

プロセッサ例外処理

ARM DUI0056DJ-00 Copyright © 1999-2001 ARM Limited. All rights reserved. 5-33

5.6 リセットハンドラリセットハンドラリセットハンドラリセットハンドラ

リセットハンドラの動作は、ソフトウェア開発対象のシステムによって異なります。例えば、以下のような動作が考えられます。

• 例外ベクタのセットアップ(P. 5-9「例外ハンドラのインストール」参照)

• スタックとレジスタの初期化

• MMUを使用している場合は、メモリシステムの初期化

• 重要 I/Oデバイスの初期化

• 割り込みのイネーブル

• コプロセッサモードまたは状態、あるいはその両方の変更

• Cに要求された変数の初期化、メインアプリケーションの呼び出し

詳細については、第 6章「ROMコードの記述」を参照して下さい。

Page 122: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

プロセッサ例外処理

5-34 Copyright © 1999-2001 ARM Limited. All rights reserved. ARM DUI0056DJ-00

5.7 未定義命令ハンドラ未定義命令ハンドラ未定義命令ハンドラ未定義命令ハンドラ

プロセッサに認識されない命令は、システムに接続されているコプロセッサに渡されます。その命令がどのコプロセッサにも認識されない場合には、未定義命令例外が生成されます。例えば、命令がコプロセッサ用の命令であるにも関わらず、浮動小数点アクセラレータなどの関連コプロセッサがシステムに接続されていないようなケースが考えられます。ただし、そのようなコプロセッサのソフトウェアエミュレータを使用することも可能です。

このようなエミュレータは:

1. 未定義命令ベクタに接続し、古い内容を保存する必要があります。

2. 未定義命令を検査し、エミュレートする必要があるかどうかをチェックします。このチェックは、SWI ハンドラが SWI の番号を抽出するときと似た方法で行いますが、エミュレータは下位 24 ビットを抽出するのではなく、ビット 27 ~ 24を抽出する必要があります。

これらのビットに基づき、以下の方法でその命令がコプロセッサ命令であるかどうかが決定されます。

• ビット 27~ 24 = b1110または b110xの場合、その命令はコプロセッサ命令である。

• ビット8~ 11がコプロセッサエミュレータによってその命令を処理する必要があることを示していれば、エミュレータはその命令を処理してユーザプログラムに復帰する必要がある。

3. 上記以外の場合、エミュレータはインストール時に保存されたベクタを使用して、その例外を元のハンドラ(またはチェイン内の次のエミュレータ)に渡す必要があります。

チェイン内のどのエミュレータもその命令を処理できない場合には、その命令の処理を続けることができないため、未定義命令ハンドラがエラーを通知して終了する必要があります。詳細については、P. 5-38「例外ハンドラのチェインニング」を参照して下さい。

注注注注

Thumb 命令セットにはコプロセッサ命令がないため、未定義命令ハンドラにそのような命令をエミュレートさせる必要はありません。

Page 123: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

プロセッサ例外処理

ARM DUI0056DJ-00 Copyright © 1999-2001 ARM Limited. All rights reserved. 5-35

5.8 プリフェッチアボートハンドラプリフェッチアボートハンドラプリフェッチアボートハンドラプリフェッチアボートハンドラ

システムに MMU が存在しない場合、プリフェッチアボートハンドラは単にエラーを通知して終了することができます。MMUが存在する場合には、アボートを発生させたアドレスを物理メモリにリストアする必要があります。lr_ABTは、アボートを発生さ

せた命令の次の命令のアドレスを指すため、リストアするアドレスは lr_ABT - 4に

あります。そのアドレスの仮想メモリ障害を解決できれば、命令フェッチを再試行することができます。プリフェッチアボートハンドラは、次の命令ではなく、アボートを発生させた命令と同じ命令に復帰する必要があります。例:

SUBS pc,lr,#4

Page 124: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

プロセッサ例外処理

5-36 Copyright © 1999-2001 ARM Limited. All rights reserved. ARM DUI0056DJ-00

5.9 データアボートハンドラデータアボートハンドラデータアボートハンドラデータアボートハンドラ

システムに MMU が存在しない場合、データアボートハンドラは単にエラーを通知して終了する必要があります。MMUが存在する場合は、データアボートハンドラは仮想メモリ障害を解決する必要があります。

lr_ABTはデータアボートを発生させた命令よりも 2つ先の命令を指すため、データアボートを発生させた命令の位置は lr_ABT - 8となります。

このアボートを発生させ得る命令には以下の 3つのタイプがあります。

単一レジスタロード単一レジスタロード単一レジスタロード単一レジスタロード /ストア命令(ストア命令(ストア命令(ストア命令(LDRまたはまたはまたはまたは STR))))

応答はプロセッサタイプによって異なります。

• アボートが ARM 6ベースのプロセッサで発生した場合:

— プロセッサが初期アボートモードにあるときにライトバックが要求された場合には、アドレスレジスタは更新されません。

— プロセッサが後期アボートモードにあるときにライトバックが要求された場合には、アドレスレジスタが更新されます。この変更は元に戻す必要があります。

• アボートが ARM7TDMIを含む ARM 7ベースのプロセッサで発生した場合、アドレスレジスタが更新され、この変更を元に戻す必要があります。

• アボートが ARM9™、ARM10™ あるいは StrongARM ベースのプロセッサで発生した場合、プロセッサは命令開始前に保持されていた値をそのアドレスに復元します。この変更を元に戻す操作は必要ありません。

スワップ命令(スワップ命令(スワップ命令(スワップ命令(SWP))))

この命令に関連してアドレスレジスタが更新されることはありません。

多重ロード多重ロード多重ロード多重ロード /ストア命令(ストア命令(ストア命令(ストア命令(LDMまたはまたはまたはまたは STM))))

応答はプロセッサタイプによって異なります。

• アボートが ARM 6 ベースのプロセッサまたは ARM 7 ベースのプロセッサで発生した場合に、ライトバックがイネーブルされていれば、全ての転送が発生したかのようにベースレジスタが更新されます。

レジスタリスト内にベースレジスタを指定した LDM を使用した場

合、プロセッサは後で回復できるように、上書きされた値を修正されたベース値で置き換えます。元のベースアドレスは、使用されるレジスタの数を使用して再計算できます。

• アボートが ARM9(tm)、ARM10(tm)あるいは StrongARMベースのプロセッサで発生した場合にライトバックがイネーブルされていると、命令開始前に保持されていた値がベースレジスタに復元されます。

Page 125: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

プロセッサ例外処理

ARM DUI0056DJ-00 Copyright © 1999-2001 ARM Limited. All rights reserved. 5-37

上記 3つのどのケースでも、MMUは要求された仮想メモリを物理メモリにロードすることができます。MMUのフォルトアドレスレジスタ(FAR)は、アボートを発生させたアドレスを保持します。これにより、ハンドラは復帰して命令を再実行することができます。

データアボートハンドラのサンプルコードは、install_directory/examples/databortに収録されています。

Page 126: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

プロセッサ例外処理

5-38 Copyright © 1999-2001 ARM Limited. All rights reserved. ARM DUI0056DJ-00

5.10 例外ハンドラのチェインニング例外ハンドラのチェインニング例外ハンドラのチェインニング例外ハンドラのチェインニング

状況によっては、特定の例外のソースが複数ある場合があります。例えば、以下のような状況があります。

• Angel は未定義命令を使用してブレークポイントを実装します。しかし、未定義命令例外は、コプロセッサ命令が実行されるときに、コプロセッサが存在しない場合にも発生します。

• Angel は、ユーザモードからスーパバイザモードへの切り替えや、開発中のセミホスティング要求のサポートなど、SWI を様々な目的に使用します。しかし、RTOSまたはアプリケーションが SWIを実装している場合もあります。

このような状況では、2つのアプローチで例外処理コードを拡張できます。

• 1つのハンドラを拡張する

• 複数のハンドラをチェインニングする

5.10.1 1つのハンドラを拡張するつのハンドラを拡張するつのハンドラを拡張するつのハンドラを拡張する

場合によっては、例外ハンドラ内のコードを拡張して例外のソースが何であったかを解決し、適切なコードを直接呼び出すことができます。この場合は、例外ハンドラのソースコードを修正します。

Angelは、このアプローチを簡素化できるように記述されています。Angelは SWIと未定義命令をデコードし、Angel例外ハンドラを拡張して非 Angel SWIと未定義命令を処理できます。

しかしこのアプローチは、1つの例外ハンドラを記述するときに例外の全てのソースが分かっている場合にのみ効果的です。

5.10.2 複数のハンドラをチェインニングする複数のハンドラをチェインニングする複数のハンドラをチェインニングする複数のハンドラをチェインニングする

場合によっては複数のハンドラが必要になるときがあります。標準 Angel デバッガを実行し、いくつかの他の SWI をサポートさせたいスタンドアロンのユーザアプリケーション(または RTOS)をダウンロードする状況があるとします。新たにロードされたアプリケーションに、インストールしたい完全に独立した例外ハンドラが備わっている場合でも、これで単純に Angelハンドラを置き換えることはできません。

この場合は、新しいハンドラが例外のソースを検出してそれを処理できないことを認識した場合に古いハンドラを呼び出せるように、古いハンドラのアドレスを示しておく必要があります。例えば、RTOSの SWIハンドラが、SWIが RTOS SWIでないことを検出すると Angel SWIハンドラを呼び出せば、Angel SWIハンドラがその SWIを処理する機会を得ます。

Page 127: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

プロセッサ例外処理

ARM DUI0056DJ-00 Copyright © 1999-2001 ARM Limited. All rights reserved. 5-39

このアプローチをいくつものレベルに拡張してハンドラのチェインを作成することができます。このアプローチを用いるコードでは、各ハンドラを完全に独立させることが可能ですが、1つのハンドラを使用するコードに比べると効率性の点で劣り、少なくとも必要以上にハンドラのチェインを伸ばすことによって効率性は低下します。

P. 5-11「Cからのハンドラのインストール」で示した 2つのルーチンは、両方ともベクタの古い内容を返します。この値をデコードして以下を得ることができます。

分岐命令のオフセット分岐命令のオフセット分岐命令のオフセット分岐命令のオフセット

このオフセットを使用して元のハンドラの位置を計算し、新しい分岐命令を構成してメモリ内の適切な位置にストアすることができます。代用ハンドラが例外処理に失敗すると、構成された分岐命令に分岐し、その命令が元のハンドラに分岐します。

元のハンドラのアドレスのストアに使用される位置元のハンドラのアドレスのストアに使用される位置元のハンドラのアドレスのストアに使用される位置元のハンドラのアドレスのストアに使用される位置

アプリケーションハンドラは例外処理に失敗すると、その位置からプログラムカウンタをロードする必要があります。

デバッグモニタまたは RTOS ハンドラに関する情報を使用すれば、ほとんどの場合でこのような計算は必要ありません。この場合は、次のハンドラ内でチェインする必要のある命令をアプリケーションにハードコーディングできます。このハンドラの最後のセクションで、例外の原因が処理されたことをチェックする必要があります。処理が完了していれば、ハンドラはアプリケーションに戻ることができます。処理されていなければ、チェイン内の次のハンドラを呼び出す必要があります。

注注注注

デバッグモニタハンドラの前のハンドラにチェインする場合、モニタをシステムから外すときはこのチェインを外し、アプリケーションハンドラを直接インストールする必要があります。

Page 128: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

プロセッサ例外処理

5-40 Copyright © 1999-2001 ARM Limited. All rights reserved. ARM DUI0056DJ-00

5.11 Thumb対応プロセッサでの例外処理対応プロセッサでの例外処理対応プロセッサでの例外処理対応プロセッサでの例外処理

このセクションでは、Thumb 対応プロセッサに適した例外ハンドラを記述する際に注意しておくべき点について説明します。

Thumb 対応プロセッサの例外処理メカニズムは、Thumb に対応していないプロセッサと基本的には同じです。例外が発生すると、適切なベクタテーブルエントリから次の命令がフェッチされます。

注注注注

このセクションの内容は Thumb対応 ARMプロセッサだけに適用されます。

Thumb 状態と ARM 状態のどちらの例外にも、同じベクタテーブルが使用されます。

P. 5-5「例外に対するプロセッサの応答」で説明した例外処理手順に、ARM状態に切り替える初期ステップが追加されます。

5.11.1 例外に対する例外に対する例外に対する例外に対する Thumbプロセッサの応答プロセッサの応答プロセッサの応答プロセッサの応答

例外が生成されると、Thumbプロセッサは以下を行います。

1. cpsrを spsr_modeにコピーします。

2. ARM状態に切り替えます。

3. CPSRのモードビットをセットします。

4. 復帰アドレスを lr_mode にストアします。詳細については、P. 5-42「復帰アドレス」を参照して下さい。

5. プログラムカウンタに、例外のベクタアドレスをセットします。ステップ 2 でThumb状態から ARM状態に切り替えることにより、このベクタアドレスにインストールされる ARM命令(分岐または pc相対ロード)のフェッチ、デコード、実行が正しく行われます。これによって ARMコードで記述する必要のあるトップレベルベニアへの分岐が発生します。

Page 129: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

プロセッサ例外処理

ARM DUI0056DJ-00 Copyright © 1999-2001 ARM Limited. All rights reserved. 5-41

例外処理例外処理例外処理例外処理

トップレベルベニアルーチンは、プロセッサステータスと必要な全てのレジスタをスタックに保存する必要があります。例外ハンドラは以下のどちらの方法でも記述できます。

• 例外ハンドラ全体を ARMコードで記述する。

• 例外を処理する Thumb ルーチンへの BX(分岐交換)を実行する。Thumb 命令セットには spsr から cpsr を復元できる命令がないため、このルーチンを例外から戻すには ARMコードベニアに戻す必要があります。

図 5-4は、この 2番目の方法を示しています。この図が示すようにARMコードと Thumbコードを結合させる方法については、第 3 章「ARM と Thumb のインターワーキング」を参照して下さい。

図図図図 5-4 Thumb状態における例外処理状態における例外処理状態における例外処理状態における例外処理

Page 130: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

プロセッサ例外処理

5-42 Copyright © 1999-2001 ARM Limited. All rights reserved. ARM DUI0056DJ-00

5.11.2 復帰アドレス復帰アドレス復帰アドレス復帰アドレス

例外が ARM状態で発生するとき、lr_modeにストアされる値は (pc - 4)です(P. 5-7「復帰アドレスと復帰命令」参照)。しかし、例外が Thumb状態で発生する場合には、コプロセッサが例外タイプごとに異なる値を自動的にストアします。この調整が必要な理由は、ARM命令が使用するフルワードではなく、Thumb命令がハーフワードしか使用しないためです。

プロセッサがこの調整を行わなかった場合、ハンドラはプロセッサの元の状態を決定し、ARMコードではなく Thumbコードに戻るために異なる命令を使用しなければならくなります。しかしプロセッサがこの調整を行うことによって、ハンドラは例外発生時のプロセッサ状態(ARMまたは Thumb)に関係なく、1つの復帰命令で正しく復帰することができます。

以下のセクションでは、プロセッサが Thumb状態のときに例外が発生した場合に、プロセッサが lr_modeにセットする値について概説します。

SWIハンドラと未定義命令ハンドラハンドラと未定義命令ハンドラハンドラと未定義命令ハンドラハンドラと未定義命令ハンドラ

このハンドラの復帰命令(MOVS pc,lr)は、プログラムカウンタを次に実行する命

令のアドレスに変更します。このアドレスの値は (pc - 2) であるため、プロセッサがlr_modeにストアする値は (pc - 2)となります。

FIQハンドラとハンドラとハンドラとハンドラと IRQハンドラハンドラハンドラハンドラ

このハンドラの復帰命令(SUBS pc,lr,#4)は、プログラムカウンタを次に実行する

命令のアドレスに変更します。プログラムカウンタは例外発生前に更新されるため、次の命令の位置は (pc - 4)です。したがって、プロセッサが lr_modeにストアする値は pcとなります。

プリフェッチアボートハンドラプリフェッチアボートハンドラプリフェッチアボートハンドラプリフェッチアボートハンドラ

このハンドラの復帰命令(SUBS pc,lr,#4)は、プログラムカウンタをアボートされ

た命令のアドレスに変更します。プログラムカウンタは例外発生前に更新されないため、アボートされた命令の位置は (pc - 4)です。したがって、プロセッサが lr_modeにストアする値は pcとなります。

データアボートハンドラデータアボートハンドラデータアボートハンドラデータアボートハンドラ

このハンドラの復帰命令(SUBS pc,lr,#8)は、プログラムカウンタをアボートされ

た命令のアドレスに変更します。プログラムカウンタは例外発生前に更新されるため、アボートされた命令の位置は (pc - 6)です。したがって、プロセッサが lr_modeにストアする値は(pc + 2)となります。

Page 131: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

プロセッサ例外処理

ARM DUI0056DJ-00 Copyright © 1999-2001 ARM Limited. All rights reserved. 5-43

5.11.3 プロセッサ状態の決定プロセッサ状態の決定プロセッサ状態の決定プロセッサ状態の決定

例外ハンドラは、例外発生時にプロセッサが ARM 状態と Thumb 状態のどちらにあったかを決定しなければならない場合があります。SWI ハンドラは特にプロセッサ状態を読み出す必要がある可能性があります。プロセッサ状態は、SPSRの Tビットを検査することで確認できます。このビットは、Thumb状態ではセットされ、ARM状態ではクリアされます。

ARMと Thumbのどちらの命令セットにも SWI命令があります。Thumb状態から SWI

を呼び出す場合には、以下の 3つの事柄に注意する必要があります。

• SWI命令のアドレスは、(lr - 4)ではなく (lr - 2)にある。

• 命令自体は 16ビットであるため、ハーフワードロードを実行する必要がある(図5-5参照)。

• SWI番号は、ARM状態では 24ビットで保持されるが、Thumb状態では 8ビットで保持される。

図図図図 5-5 Thumb SWI命令命令命令命令

例 5-19は、両方のソースからの SWIを処理する ARMコードを示しています。以下に注意して下さい。

• do_swi_x ルーチンのそれぞれが Thumb 状態へのスイッチを実行し、必要に応じてコード密度を向上するために Thumb状態に戻る。

• switch()ステートメントを含むC関数への呼び出しによってジャンプテーブルを置き換え、SWIを実行することができる。

• SWIの値は、それが呼び出されたときの状態によって違う方法で処理できる。

• Thumb 状態からアクセス可能な SWI の値の範囲は、SWI を動的に呼び出すことによって広げることができる(P. 5-14「SWIハンドラ」参照)。

例例例例 5-19

T_bit EQU 0x20 ; Thumb bit of CPSR/SPSR, that is, bit 5. : :SWIHandler STMFD sp!, {r0-r3,r12,lr} ; Store registers. MRS r0, spsr ; Move SPSR into general purpose register. TST r0, #T_bit ; Occurred in Thumb state? LDRNEH r0,[lr,#-2] ; Yes: load halfword and...

Page 132: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

プロセッサ例外処理

5-44 Copyright © 1999-2001 ARM Limited. All rights reserved. ARM DUI0056DJ-00

BICNE r0,r0,#0xFF00 ; ...extract comment field. LDREQ r0,[lr,#-4] ; No: load word and... BICEQ r0,r0,#0xFF000000 ; ...extract comment field.

; r0 now contains SWI number

CMP r0, #MaxSWI ; Rangecheck LDRLS pc, [pc, r0, LSL#2] ; Jump to the appropriate routine. B SWIOutOfRangeswitable DCD do_swi_1 DCD do_swi_2 : :do_swi_1 ; Handle the SWI. LDMFD sp!, {r0-r3,r12,pc}^ ; Restore the registers and return.do_swi_2 :

Page 133: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

プロセッサ例外処理

ARM DUI0056DJ-00 Copyright © 1999-2001 ARM Limited. All rights reserved. 5-45

5.12 システムモードシステムモードシステムモードシステムモード

ARMアーキテクチャでは、ユーザモードを 15個の汎用レジスタ、pc、CPSRを使用するモードとして定義しています。このモードの他にも 5 つの特権プロセッサモードがあり、それぞれが専用の SPSR と、15 個のユーザモード汎用レジスタのいくつかに置き換わるレジスタを使用します。

注注注注

このセクションの内容は、ARMアーキテクチャ v4、v4Tあるいはそれ以降のアーキテクチャを実装するプロセッサだけに適用されます。

プロセッサ例外が発生すると、現在のプログラムカウンタがその例外モードのリンクレジスタにコピーされ、CPSRがその例外モードの SPSRにコピーされます。これにより CPSR が例外に依存する形で変更され、プログラムカウンタには例外ハンドラを起動する例外定義アドレスがセットされます。

ARMサブルーチンコール命令(BL)は、プログラムカウンタの変更前に復帰アドレスを r14にコピーするため、このサブルーチンの復帰命令は r14を pcに移動します(MOVpc,lr)。

これらの動作は、例外を処理する ARM モードでサブルーチンが呼び出される場合に、サブルーチン復帰アドレスが例外復帰アドレスで上書きされないように、同じタイプの別の例外を発生させないようにするためです。

(旧バージョンの ARM アーキテクチャでは、この問題は例外コード内にサブルーチンコールを含めないように注意するか、特権モードからユーザモードに変更することによって解決されていました。一つ目の解決方法は制約があまりにも大きく、また二つ目の方法では正しく実行する必要があるタスクに特権アクセスを割り当てられません。)

ARM アーキテクチャ v4 以上では、この問題を解決するためにシステムモードと呼ばれるプロセッサモードが追加されています。システムモードは、ユーザモードレジスタを共有する特権プロセッサモードです。特権モードのタスクはこのモードで実行することが可能であり、例外によるリンクレジスタの上書きを防ぐことができます。

注注注注

例外からシステムモードを開始することはできません。例外ハンドラはシステムモードに入るときに CPSRを修正します。詳細については、P. 5-26「リエントラント割り込みハンドラ」を参照して下さい。

Page 134: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

プロセッサ例外処理

5-46 Copyright © 1999-2001 ARM Limited. All rights reserved. ARM DUI0056DJ-00

Page 135: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

ARM DUI0056DJ-00 Copyright © 1999-2001 ARM Limited. All rights reserved. 6-1

第 6章ROMコードの記述コードの記述コードの記述コードの記述

本章では、組み込みアプリケーションイメージのビルド方法を説明します。これらのイメージは一般的に ROMまたはフラッシュメモリにプログラムします。また、ROMコードを記述する際に最も犯しやすい誤りを回避するためのヒントも記載しています。

本章は以下のセクションから構成されています。

• ROMコードの記述について:P. 6-2

• メモリマップに関する注意点:P. 6-4

• システムの初期化:P. 6-7

• セミホスティングを使用した Cの基本サンプル:P. 6-11

• アドレス 0への ROMイメージのロード:P. 6-14

• アドレス 0への ROMイメージのロード:P. 6-14

• 分散ローディングと再マッピングの使用:P. 6-25

• セミホステッドアプリケーションの割り込み処理:P. 6-29

• 組み込みアプリケーションの割り込み処理:P. 6-34

• メモリマップ I/Oを使用した分散ローディング:P. 6-37

• トラブルシューティング:P. 6-44

• コードサイズとデータサイズの測定:P. 6-47

Page 136: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

ROMコードの記述

6-2 Copyright © 1999-2001 ARM Limited. All rights reserved. ARM DUI0056DJ-00

6.1 ROMコードの記述についてコードの記述についてコードの記述についてコードの記述について

本章では、ROMコードの記述方法を単純なイメージと複雑なイメージに分けて説明します。初期化データ、スタックポインタ、割り込みなどに関する情報を交えながら、初期化コードのサンプルを紹介しています。

本章には分散ローディングを使用して複雑なイメージをビルドするサンプルも含まれています。リンカと分散ローディングの詳細については、ADSリンカ /ユーティリティガイドを参照して下さい。

注注注注

本章で紹介するサンプルは ARM Integratorボードをターゲットとしており、install_directory\Examples\embedded に収録されています。これらのサンプルを元に、システムの初期化コードを記述することができます。

参考サンプルコード(embed、embed_cpp、ledflash、rps_irq)は、複雑さの度

合いによって異なるコンフィギュレーションでビルドすることができます。

• Cライブラリとリンクする単純なセミホステッドアプリケーションとして。このサンプルでは、I/O に C ライブラリのセミホスティング SWI 関数を使用します(P. 6-11「セミホスティングを使用した Cの基本サンプル」参照)。

• Cライブラリにリンクし、分散ローディングを使用してアドレス 0x0で実行するROM に組み込むことのできるアプリケーションとして。このサンプルではセミホスティング SWI関数を使用しない代わりに、I/Oの再対象化レイヤを使用します(P. 6-14「アドレス 0への ROMイメージのロード」参照)。

• 分散ローディングとメモリの再マッピングで、初期化後に RAMを 0x0に移動するアプリケーションとして(P. 6-25「分散ローディングと再マッピングの使用」参照)

この他、関数の再対象化とプロセッサの初期化を例示した以下のファイルが収録されています。

• retarget.cは、低レベル入出力の再対象化レイヤを実装します。

• stack.s、heap.s, uart.c、scat_c.scfは、分散ファイルを使用したスタック、ヒープ、メモリマップペリフェラルの配置を例示しています。

• init.sは、長さとオフセットを使用した各モードのスタックポインタの初期化を例示しています。

• cacheサブディレクトリには、各種 ARMコアのキャッシュおよびクロックの初期化コードが収録されています。

Page 137: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

ROMコードの記述

ARM DUI0056DJ-00 Copyright © 1999-2001 ARM Limited. All rights reserved. 6-3

CodeWarrior IDEプロジェクトのサンプルは embed.mcp、embed_cpp.mcp、

ledflash.mcp、rps_irq.mcpに収録されています。

その他のサンプルコードおよび ROM コードの記述に関する詳細については、ARMファームウェアスイート(AFS)のサンプルコードと説明書を参照して下さい。AFSの詳しい説明については、ARMが提供している以下の文書を参照して下さい。

• ARM Firmware Suite User Guide

• ARM Firmware Suite Reference Guide

Page 138: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

ROMコードの記述

6-4 Copyright © 1999-2001 ARM Limited. All rights reserved. ARM DUI0056DJ-00

6.2 メモリマップに関する注意点メモリマップに関する注意点メモリマップに関する注意点メモリマップに関する注意点

組み込みARMアプリケーションの設計に関して最も注意しなければならないのはメモリマップのレイアウトであり、特にアドレス 0x0 に配置するメモリに気を付ける必要

があります。リセット後、プロセッサは命令フェッチを 0x0 から開始するため、この

アドレスからアクセス可能な実行コードが存在していなければなりません。組み込みシステムでは、少なくとも起動時には、アドレス 0x0 に ROM が存在している必要があります。

6.2.1 0x0にににに ROMを配置するを配置するを配置するを配置する

最も単純なレイアウトは、メモリマップ内のアドレス 0にある ROMにアプリケーションを配置するレイアウトです(図 6-1参照)。このアプリケーションは、(アドレス 0x0

のリセットベクタで)最初の命令を実行するときに実エントリポイントに分岐することができます。

図図図図 6-1 0x0にににに ROMを配置したシステムの例を配置したシステムの例を配置したシステムの例を配置したシステムの例

ただし、このレイアウトには短所があります。ROM は RAM よりも狭く(8 ビットまたは 16 ビット)、遅いのが一般的です。このため、ベクタテーブルを介したプロセッサ例外(特に割り込み)の処理速度が低下します。また、ベクタテーブルが ROM内にあるときは、コードによって修正することができません。

例外処理の詳細については、第 5章「プロセッサ例外処理」を参照して下さい。

6.2.2 0x0にににに RAMを配置するを配置するを配置するを配置する

RAMは ROMよりも速く、幅が広いのが一般的です。このため、ベクタテーブルと割り込みハンドラに関しては、0x0にあるメモリが RAMである方が効果的です。

しかし、RAMが起動時にアドレス 0x0にあると、リセットベクタエントリに有効な命

令が存在しないことになります。したがって、起動時には 0x0 に ROM を配置し(有効なリセットベクタを配置するため)、通常の実行中は 0x0に RAMを配置できるようにしておく必要があります。リセットから通常のメモリマップへの切り替えは、メモリマップレジスタへの書き込みによって行います(P. 6-5図 6-2参照)。

DRAM

SRAM

ROM0x00000000

0x04000000

0x0F000000

0x10000000

Page 139: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

ROMコードの記述

ARM DUI0056DJ-00 Copyright © 1999-2001 ARM Limited. All rights reserved. 6-5

例えば、リセット時にはROMのエイリアスコピーを 0x0に置き、コードがRPS REMAP

レジスタへの書き込みを行うときに RAM をゼロに再マップします。詳細については、ARM Reference Peripheral Specificationを参照して下さい。

図図図図 6-2 0x0にににに RAMを配置したシステムの例を配置したシステムの例を配置したシステムの例を配置したシステムの例

0x0へのへのへのへの RAMの実装の実装の実装の実装

以下は RAMを 0x0に実装するイベントシーケンスの例です。

1. 起動時に0x0でRESETベクタを(ROMのエイリアスコピーから)フェッチします。

2. RESETベクタを実行します。

LDR PC, =0x0F000004

これによって次の ROM命令の実アドレスへのジャンプが発生します。このコードは位置独立命令にアセンブルされます。

LDR PC, [PC, offset]

3. REMAPレジスタへの書き込みを行い、REMAP = 1をセットします。

4. P. 6-7「システムの初期化」の手順に従って、残りの初期化コードを実行します。

Page 140: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

ROMコードの記述

6-6 Copyright © 1999-2001 ARM Limited. All rights reserved. ARM DUI0056DJ-00

システムデコーダシステムデコーダシステムデコーダシステムデコーダ

ROMは、システムメモリデコーダによってアドレス 0x0にエイリアスを置くことがで

きます。単純なメモリデコーダは以下のようにこれを実装することができます。

case ADDR(31:24) is when "0x00" if REMAP = "0" then select ROM else select SRAM when "0x0F" select ROM when ....

Page 141: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

ROMコードの記述

ARM DUI0056DJ-00 Copyright © 1999-2001 ARM Limited. All rights reserved. 6-7

6.3 システムの初期化システムの初期化システムの初期化システムの初期化

初期化は以下の 2段階で実行します。

1. 例外ベクタ、スタック、I/Oなどの実行環境を初期化します。

2. Cライブラリおよびアプリケーション(C変数など)を初期化します。

ホステッドアプリケーションの場合、実行環境は OS起動時に初期化されます(初期化は Angel、RTOS、ARMulatorなどによって行われます)。その後、アプリケーションは自動的に main() 関数に入り、__main の C ライブラリコードがこのアプリケーションを初期化します。

オペレーティングシステムのない組み込みアプリケーションの場合は、ROM内のコードがアプリケーションをそれ自身で初期化させ、実行を開始させる必要があります。リセット時には自動初期化は発生しないため、アプリケーションのエントリポイントである程度の初期化を実行してから Cコードを呼び出す必要があります。

リセット後は、アドレス 0x0にある命令が制御を初期化コードに渡す必要があります。

この初期化コードは以下を行う必要があります。

• 例外ベクタのセットアップ

• メモリシステムの初期化

• スタックポインタレジスタの初期化

• 重要 I/Oデバイスの初期化

• プロセッサモードの変更(必要時)

• プロセッサ状態の変更(必要時)

環境の初期化が環境すると、シーケンスはアプリケーションの初期化に続き、Cコードに入ります。

上記については以下で詳しく説明します。サンプルコードについては、P. 6-16例 6-3および P. 6-17例 6-4を参照して下さい。

6.3.1 実行環境の初期化実行環境の初期化実行環境の初期化実行環境の初期化

アプリケーション開始前に初期化する必要がある実行環境には、いくつかのアスペクトがあります。このアプリケーションをオペレーティングシステムがホストしている場合、初期化はアプリケーションローダによって実行されます。このアプリケーションがスタンドアロンで実行するとき、C ライブラリが環境の初期化を実行し、アプリケーションのエントリポイントをmain()で呼び出すことができます。ただし分散ロー

ディングを使用する場合は、__user_intial_stackheap() を再対象化してスタッ

クとヒープを初期化する必要があります。これを示すサンプルが retarget.cに収録

されています。

Page 142: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

ROMコードの記述

6-8 Copyright © 1999-2001 ARM Limited. All rights reserved. ARM DUI0056DJ-00

リセット後の ARMプロセッサコアの状態は以下のとおりです。

• SVCモード

• 割り込みディセーブル

• ARM状態

エントリポイントの識別エントリポイントの識別エントリポイントの識別エントリポイントの識別

実行イメージにはエントリポイントがなければなりません。通常、ROM内に配置可能な組み込みイメージは 0x0 にエントリポイントを置きます。エントリポイントは、ア

センブラディレクティブ ENTRYを使用して、初期化コード内で定義することができま

す。組み込みアプリケーションには複数のエントリポイントを使用することも可能です。複数のエントリポイントがあるときは、-entryを使用してその 1つを初期エントリポイントとして指定する必要があります。詳細については、ADSリンカ /ユーティリティガイドの「リンカによるエントリポイントの選択」を参照して下さい。

main()関数を含む Cプログラムを作成した場合には、Cライブラリ初期化コード内にもエントリポイントがあります。ライブラリを使用するアプリケーションの作成については、ADSリンカ /ユーティリティガイドの「ライブラリ」を参照して下さい。

例外ベクタのセットアップ例外ベクタのセットアップ例外ベクタのセットアップ例外ベクタのセットアップ

初期化コードは、以下のように必要な例外ベクタをセットアップする必要があります。

• ROMがアドレス 0x0にあるとき、ベクタは各例外のハンドラに分岐するハードコーディングされた命令シーケンスで構成します。

• ROM が上記以外の位置にある場合には、ベクタを初期化コードで動的に初期化する必要があります。通常、この初期化はベクタテーブルを ROM から RAM にコピーすることによって行われます(P.6-25「分散ローディングと再マッピングの使用」参照)。

典型的な初期化コードのサンプルについては、P. 6-17例 6-4を参照して下さい。

メモリシステムの初期化メモリシステムの初期化メモリシステムの初期化メモリシステムの初期化

システムにメモリ管理ユニットまたは保護ユニットが存在する場合には、以下の時点でこれを初期化する必要があります。

• 割り込みがイネーブルされる前

• スタックの使用によって暗示的または明示的に、特定アドレスでアクセス可能なRAMに依存する可能性のあるコードが呼び出される前

キャッシュの初期化コードのサンプルは、Examples\embedded\cache ディレクト

リに収録されています。

Page 143: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

ROMコードの記述

ARM DUI0056DJ-00 Copyright © 1999-2001 ARM Limited. All rights reserved. 6-9

スタックポインタの初期化スタックポインタの初期化スタックポインタの初期化スタックポインタの初期化

初期化コードはスタックポインタレジスタを初期化します。使用する割り込みと例外によっては、以下のスタックポインタの一部または全部を初期化しなければならない場合があります。

sp_SVC 必ず初期化する必要があります。

sp_IRQ IRQ 割り込みを使用する場合は初期化する必要があります。このポインタは割り込みがイネーブルされる前に初期化する必要があります。

sp_FIQ FIQ 割り込みを使用する場合は初期化する必要があります。このポインタは割り込みがイネーブルされる前に初期化する必要があります。

sp_ABT データアボートとプリフェッチアボートを処理するには、これを初期化

する必要があります。

sp_UND 未定義命令を処理するには、これを初期化する必要があります。

通常、単純な組み込みシステムでは sp_ABT と sp_UND を使用しません。しかし、デ

バッグ目的ではこれらのポインタを初期化した方がよいかもしれません。

ユーザモードに切り替えてアプリケーションの実行を開始する場合は、スタックポインタ sp_USRをセットアップできます。

注意注意注意注意

分散ローディングを使用する場合は、関数 __user_initial_stackheap() を再対

象化してスタックとヒープを配置する必要があります。これを怠ると、Cライブラリによるデフォルト実装によって、分散ローディングの使用時には定義されない

Image$$ZI$$Limitの使用が試行されるため、リンクエラーが発生する可能性があり

ます。この関数の再対象化については、P. 6-14「アドレス 0への ROMイメージのロード」を参照して下さい。

重要重要重要重要 I/Oデバイスの初期化デバイスの初期化デバイスの初期化デバイスの初期化

重要 I/Oデバイスとは、割り込みをイネーブルする前に初期化する必要のある全てのデバイスを指します。通常、これらのデバイスはこの時点で初期化する必要があります。これに反すると、割り込みがイネーブルされているときに偽の割り込みが発生する可能性があります。

プロセッサモードの変更プロセッサモードの変更プロセッサモードの変更プロセッサモードの変更

この段階では、プロセッサモードはまだスーパバイザモードにあります。アプリケーションをユーザモードで実行する場合はユーザモードに変更し、ユーザモードの spレジスタ sp_USRを初期化する必要があります。

Page 144: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

ROMコードの記述

6-10 Copyright © 1999-2001 ARM Limited. All rights reserved. ARM DUI0056DJ-00

プロセッサ状態の変更プロセッサ状態の変更プロセッサ状態の変更プロセッサ状態の変更

Thumb対応プロセッサを含む全ての ARMコアは、リセット時に ARM状態で始動します。初期化コード(少なくともリセットハンドラ)は ARMコードで記述する必要があります。アプリケーションを Thumb用にコンパイルする場合には、main()を Thumb

コードで記述します。リンカは、ARM初期化コードと Thumbアプリケーション間で状態を自動的に変更する ARM-Thumb インターワーキングベニアを挿入することができます。

6.3.2 アプリケーションの初期化アプリケーションの初期化アプリケーションの初期化アプリケーションの初期化

アプリケーションは以下によって初期化されます。

• 初期化値を書き込み可能データ領域にコピーすることにより、ゼロ以外の書き込み可能データを初期化する。

• ZI書き込み可能データ領域にゼロをセットする。

メモリの初期化後、例えば C ライブラリコード内のアプリケーションのエントリポイントに制御が渡されます。

Cコードによるメモリの初期化コードによるメモリの初期化コードによるメモリの初期化コードによるメモリの初期化

初期化されるどの変数(RW)の初期値も ROM から RAM にコピーする必要があります。他の全ての ZI変数はゼロに初期化する必要があります。__main で呼び出されるライブラリの初期化コードでこのコピーと初期化を実行します。

注注注注

リンカは RO コード、RW データ、ZI データにメモリアドレスを割り当てます。分散ロード記述ファイルを使用しない場合、リンカはデフォルトレイアウトのうちの 1 つを使用します。分散ローディングのサンプルについては、P. 6-14「アドレス 0への ROMイメージのロード」および P. 6-25「分散ローディングと再マッピングの使用」を参照して下さい。

メイン関数の使用メイン関数の使用メイン関数の使用メイン関数の使用

コンパイラは main() と呼ばれる関数をコンパイルするときに、シンボル __main へ

の参照を生成することによって、リンカに ANSI Cライブラリから基本 Cランタイムシステムをインクルードさせます。(シンボル __mainはエントリポイントとしてマーキ

ングされます。)

Page 145: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

ROMコードの記述

ARM DUI0056DJ-00 Copyright © 1999-2001 ARM Limited. All rights reserved. 6-11

6.4 セミホスティングを使用したセミホスティングを使用したセミホスティングを使用したセミホスティングを使用した Cの基本サンプルの基本サンプルの基本サンプルの基本サンプル

このセクションで紹介するサンプルは、セミホスティング SWIを使用するアプリケーションコードを示しています。printf()は、セミホスティング SWIを使用してデバッガコンソールに情報を表示する C ライブラリ関数への呼び出しとしてコンパイルされます。このアプリケーションは 1つの Cファイルで構成されています。

main.cのコードはinstall_directory\Examples\Embedded\embedディレクト

リに収録されています。また、この一部を参考として P. 6-13例 6-1にも示しています。

このサンプルを CodeWarrior IDEからビルドするには:

1. CodeWarrior IDEプロジェクト embed.mcpを使用します。

2. Target=Semihostedを選択します。

このサンプルをコマンドラインからビルドするには、build_a.batを実行するか、以

下のステップに従って下さい。

1. 以下のいずれかのコマンドを使用して Cファイル main.cをコンパイルします。

armcc -g -O1 -c main.c(ARM向けにコンパイルする場合)

tcc -g -O1 -c main.c (Thumb向けにコンパイルする場合)

上記において:-O1 最適化レベルを指定します。-g コンパイラにデバッグテーブルを追加するように指示します。-c コンパイラにコンパイルだけ(リンクなし)を行うように指示します。

2. 以下のコマンドを使用してこのイメージをリンクさせます。

armlink main.o -o embed.axf

上記において:

-o 出力ファイルとして embed.axfを指定します。

3. ARMulatorを使用してイメージをテストするか、Multi-ICEまたは Angelを使用してこのイメージを開発ボードにダウンロードします。

Page 146: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

ROMコードの記述

6-12 Copyright © 1999-2001 ARM Limited. All rights reserved. ARM DUI0056DJ-00

6.4.1 メモリマップメモリマップメモリマップメモリマップ

図 6-3は、基本サンプルのメモリマップを示しています。

図図図図 6-3 基本サンプルのメモリマップ基本サンプルのメモリマップ基本サンプルのメモリマップ基本サンプルのメモリマップ

デフォルトでは、リンカはコードの開始位置をアドレス 0x8000 に設定します。RW

データはプログラムコードのすぐ上に配置され、ZIデータは RWデータの上に配置されます。

ARMulatorを使用した場合には、デフォルトでスタックポインタ spが 0x08000000に

初期化されます。開発ボードを使用する場合には、$top_of_memoryを設定する必要

があります。例えば、ほとんどの(拡張されていない)ARM Integrator ボードでは、$top_of_memoryに 0x40000を設定します。

Page 147: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

ROMコードの記述

ARM DUI0056DJ-00 Copyright © 1999-2001 ARM Limited. All rights reserved. 6-13

6.4.2 サンプルコードサンプルコードサンプルコードサンプルコード

例 6-1の Cコードフラグメントは、セミホスティング SWIを使用したテキストの出力を示しています。demo_malloc()、demo_printf()、demo_float_print()、

demo_sprintf()の定義については、main.cのソースコードを参照して下さい。

#ifdef EMBEDDEDによって選択されるコードは、P. 6-14「アドレス 0への ROMイメージのロード」と他のサンプルで使用しています。

例例例例 6-1 main.cの一部の一部の一部の一部

int main(void){ printf("C Library Example\n"); #ifdef EMBEDDED/* ensure no C library functions that uses semihosting SWIs are linked */ #pragma import(__use_no_semihosting_swi) #endif demo_printf(); demo_sprintf(); demo_float_print(); demo_malloc(); return 0;}

Page 148: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

ROMコードの記述

6-14 Copyright © 1999-2001 ARM Limited. All rights reserved. ARM DUI0056DJ-00

6.5 アドレスアドレスアドレスアドレス 0へのへのへのへの ROMイメージのロードイメージのロードイメージのロードイメージのロード

分散ローディングを使用すれば、コードとデータを柔軟にメモリマップにマッピングすることができます。これらのオプションの詳細については、ADSリンカ /ユーティリティガイドを参照して下さい。

この例で使用する分散ローディング記述ファイル scat_b.scfは

install_directory\Examples\Embedded\embedに収録されています。

6.5.1 メモリマップメモリマップメモリマップメモリマップ

図 6-4は以下を示しています。

• ROMを 0x0に固定し、再マップしない。

• RAMを 0x28000000に配置し、データ、スタック、ヒープを保持させる。

• UARTのメモリマップ I/Oを 0x16000000に配置する。

図図図図 6-4 単純な分散ローディングのメモリマップ単純な分散ローディングのメモリマップ単純な分散ローディングのメモリマップ単純な分散ローディングのメモリマップ

6.5.2 分散ロード記述ファイル分散ロード記述ファイル分散ロード記述ファイル分散ロード記述ファイル

P. 6-15例 6-2が示す分散ロード記述ファイルは、以下を定義しています。

• 0x0に配置する 1つのロード領域、ROM_LOAD

• 5つの実行領域:

— ROM_EXEC(0x0)は、ライブラリコードを含む全ての読み出し専用コードを保持します。vectors.o 内の例外ベクタテーブルが最初にこの領域に配置されます。他の全ての読み出し専用コード(*)は vectors.oの後に配置されます。

Page 149: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

ROMコードの記述

ARM DUI0056DJ-00 Copyright © 1999-2001 ARM Limited. All rights reserved. 6-15

— RAM(0x28000000)は、アプリケーションの RW および ZI データ領域を保持します。

— HEAP は ZI データのすぐ上に配置されます。オブジェクト heap.o は、ヒープベースの設定に使用されるシンボルを保持します。ヒープはこのアドレスから上向きに展開されます。

— STACKSは 0x28080000に配置されます。オブジェクト stack.oは、スタック最上位の設定に使用されるシンボルを保持します。スタックはこのアドレスから下向きに展開されます。

— UART0は 0x16000000に配置されます。オブジェクト uart.oは、メモリマップ I/Oの予約に使用されるシンボルを保持します。

注注注注

UNINITエントリは、マーキングされた領域が Cライブラリ初期化コードによってゼロ初期化されないことを意味します。

例例例例 6-2 scat_b.scf

ROM_LOAD 0x0{ ROM_EXEC 0x0 { vectors.o (Vect, +First) * (+RO) } RAM 0x28000000 { * (+RW,+ZI) } HEAP +0 UNINIT { heap.o (+ZI) } STACKS 0x28080000 UNINIT { stack.o (+ZI) } UART0 0x16000000 UNINIT { uart.o (+ZI) }}

Page 150: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

ROMコードの記述

6-16 Copyright © 1999-2001 ARM Limited. All rights reserved. ARM DUI0056DJ-00

6.5.3 サンプルコードサンプルコードサンプルコードサンプルコード

例 6-3のコードは、例外ベクタと例外ハンドラのサンプルを示しています。このアプリケーションでは、ROM が 0x0 に固定され、例外テーブルが 0x0 にハードコーディン

グされます。P. 6-14「アドレス 0への ROMイメージのロード」では、ROM/RAMの再マッピングが発生し、ベクタが ROMから RAMにコピーされます。

例例例例 6-3 vectors.s

AREA Vect, CODE, READONLY; Where there is ROM fixed at 0x0 (build_b), these are hard-coded at 0x0.; Where ROM/RAM remapping occurs (build_c), these are copied from ROM to RAM.; The copying is done automatically by the C library code inside __main.; *****************; Exception Vectors; *****************; Note: LDR PC instructions are used here, though branch (B) instructions; could also be used, unless the ROM is at an address >32MB. LDR PC, Reset_Addr LDR PC, Undefined_Addr LDR PC, SWI_Addr LDR PC, Prefetch_Addr LDR PC, Abort_Addr NOP ; Reserved vector LDR PC, IRQ_Addr LDR PC, FIQ_Addr IMPORT Reset_Handler ; In init.s

Reset_Addr DCD Reset_HandlerUndefined_Addr DCD Undefined_HandlerSWI_Addr DCD SWI_HandlerPrefetch_Addr DCD Prefetch_HandlerAbort_Addr DCD Abort_HandlerIRQ_Addr DCD IRQ_HandlerFIQ_Addr DCD FIQ_Handler

; ************************; Exception Handlers; The following dummy handlers do not do anything useful in this example.; They are set up here for completeness.Undefined_Handler B Undefined_HandlerSWI_Handler B SWI_HandlerPrefetch_Handler B Prefetch_HandlerAbort_Handler B Abort_Handler

Page 151: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

ROMコードの記述

ARM DUI0056DJ-00 Copyright © 1999-2001 ARM Limited. All rights reserved. 6-17

IRQ_Handler B IRQ_HandlerFIQ_Handler B FIQ_Handler END

例 6-4 のコードは ROM/RAM の再マッピングを(必要に応じて)実行し、各モードのスタックポインタと割り込みを初期化し、最後に Cライブラリ内の __mainに分岐し

ます(__main は結果的に main() を呼び出します)。リセット時、ARM コアはスーパバイザモード(SVC)、ARM状態で起動し、IRQと FIQがディセーブルされます。

例例例例 6-4 init.s

AREA Init, CODE, READONLY

; - Set up if ROM/RAM remapping required; GBLL ROM_RAM_REMAP;ROM_RAM_REMAP SETL {TRUE} ; change to {FALSE} if remapping not required

; - ensure no functions that use semihosting SWIs are linked from the C library IMPORT __use_no_semihosting_swi

; - Standard definitions of mode bits and interrupt (I & F) flags in PSRsMode_USR EQU 0x10Mode_FIQ EQU 0x11Mode_IRQ EQU 0x12Mode_SVC EQU 0x13Mode_ABT EQU 0x17Mode_UNDEF EQU 0x1BMode_SYS EQU 0x1F ; available on ARM Arch v4 and laterI_Bit EQU 0x80 ; when I bit is set, IRQ is disabledF_Bit EQU 0x40 ; when F bit is set, FIQ is disabled

; --- System memory locations

CM_ctl_reg EQU 0x1000000C ; Address of Core Module Control RegisterRemap_bit EQU 0x04 ; Bit 2 is remap bit of CM_ctl

; --- Amount of memory (in bytes) allocated for stacks

Len_FIQ_Stack EQU 0Len_IRQ_Stack EQU 256Len_ABT_Stack EQU 0Len_UND_Stack EQU 0Len_SVC_Stack EQU 1024; Len_USR_Stack EQU 1024

Page 152: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

ROMコードの記述

6-18 Copyright © 1999-2001 ARM Limited. All rights reserved. ARM DUI0056DJ-00

; Add lengths >0 for FIQ_Stack, ABT_Stack, UNDEF_Stack if you need them; offsets will be loaded as immediate values; Offsets must be 8 byte aligned

Offset_FIQ_Stack EQU 0Offset_IRQ_Stack EQU Offset_FIQ_Stack + Len_FIQ_StackOffset_ABT_Stack EQU Offset_IRQ_Stack + Len_IRQ_Stack Offset_UND_Stack EQU Offset_ABT_Stack + Len_ABT_StackOffset_SVC_Stack EQU Offset_UND_Stack + Len_UND_Stack; Offset_USR_Stack EQU Offset_SVC_Stack + Len_SVC_Stack

ENTRY

; --- Perform ROM/RAM remapping, if required IF :DEF: ROM_RAM_REMAP

; On reset, an aliased copy of ROM is at 0x0.; Continue execution from 'real' ROM rather than aliased copy LDR pc, =Instruct_2 Instruct_2 ; Remap by setting Remap bit of the CM_ctl register LDR r1, =CM_ctl_reg LDR r0, [r1] ORR r0, r0, #Remap_bit STR r0, [r1]; RAM is now at 0x0.; The exception vectors (in vectors.s) must be copied from ROM to the RAM; The copying is done later by the C library code inside __main

ENDIF

EXPORT Reset_HandlerReset_Handler

; --- Initialize stack pointer registers; Enter each mode in turn and set up the stack pointer IMPORT top_of_stacks ;defined in stack.s and located by scatter file LDR r0, =top_of_stacks

; MSR CPSR_c, #Mode_FIQ:OR:I_Bit:OR:F_Bit ; No interrupts; SUB sp, r0, #Offset_FIQ_Stack

MSR CPSR_c, #Mode_IRQ:OR:I_Bit:OR:F_Bit ; No interrupts SUB sp, r0, #Offset_IRQ_Stack

; MSR CPSR_c, #Mode_ABT:OR:I_Bit:OR:F_Bit ; No interrupts; SUB sp, r0, #Offset_ABT_Stack

; MSR CPSR_c, #Mode_UND:OR:I_Bit:OR:F_Bit ; No interrupts

Page 153: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

ROMコードの記述

ARM DUI0056DJ-00 Copyright © 1999-2001 ARM Limited. All rights reserved. 6-19

; SUB sp, r0, #Offset_UND_Stack

MSR CPSR_c, #Mode_SVC:OR:I_Bit:OR:F_Bit ; No interrupts SUB sp, r0, #Offset_SVC_Stack

; ...

; --- Initialize memory system IF :DEF: CACHE IMPORT Clock_Speed ; in CMclocks.s IMPORT Cache_Init ; in the core-specific files e.g. 940T.s BL Clock_Speed BL Cache_Init ENDIF

; --- Initialize critical IO devices ; ...

; --- Now change to User mode and set up User mode stack. MSR CPSR_c, #Mode_USR:OR:F_Bit ; IRQs now enabled SUB sp, r0, #Offset_USR_Stack IMPORT __main

; --- Now enter the C code B __main ; note use B not BL ; because an application will never return this way END

例 6-5 のコードは、低レベル I/O の再対象化レイヤを実装しています。通常、これにターゲット依存の fputc()や ferror()などの実装を含めます。このサンプルでは、

fputc()、ferror()、_sys_exit()、_ttywrch()、

__user_initial_stackheap()を実装しています。

ホストデバッガのコンソールにテキストを表示する目的でセミホスティング SWIが使用されています。このメカニズムは ARMulator、Angel、Multi-ICE、EmbeddedICEの間で移植することができます。serial.cは、ARM Integratorボードのシリアルポートから文字を出力するオプションです。serial.cを使用するには、このコードに

#define USE_SERIAL_PORTを追加するか、-DUSE_SERIAL_PORTを使用してコン

パイルします。

例例例例 6-5 retarget.c

/*** This implements a 'retarget' layer for low-level IO. Typically, this** would contain your own target-dependent implementations of fputc(),** ferror(), etc.

Page 154: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

ROMコードの記述

6-20 Copyright © 1999-2001 ARM Limited. All rights reserved. ARM DUI0056DJ-00

** ** This example provides implementations of fputc(), ferror(),** _sys_exit(), _ttywrch() and __user_initial_stackheap().**** Here, semihosting SWIs are used to display text onto the console ** of the host debugger. This mechanism is portable across ARMulator,** Angel, Multi-ICE and EmbeddedICE.**** Alternatively, to output characters from the serial port of an ** ARM Integrator Board (see serial.c), use:**** #define USE_SERIAL_PORT**** or compile with **** -DUSE_SERIAL_PORT*/ #include <stdio.h> #include <rt_misc.h> #ifdef __thumb /* Thumb Semihosting SWI */ #define SemiSWI 0xAB #else /* ARM Semihosting SWI */ #define SemiSWI 0x123456 #endif

/* Write a character */__swi(SemiSWI) void _WriteC(unsigned op, char *c); #define WriteC(c) _WriteC (0x3,c)

/* Exit */__swi(SemiSWI) void _Exit(unsigned op, unsigned except); #define Exit() _Exit (0x18,0x20026)

struct __FILE { int handle; /* Add whatever you need here */}; FILE __stdout;

extern unsigned int bottom_of_heap; extern void sendchar( char *ch ); /* in serial.c */

int fputc(int ch, FILE *f){ char tempch=ch; /* Place your implementation of fputc here, for example write a character */ /* to a UART, or to the debugger console with SWI WriteC */ #ifdef USE_SERIAL_PORT sendchar( &tempch );

Page 155: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

ROMコードの記述

ARM DUI0056DJ-00 Copyright © 1999-2001 ARM Limited. All rights reserved. 6-21

#else WriteC( &tempch ); #endif return ch; }

int ferror(FILE *f){ /* Your implementation of ferror */ return EOF;}

void _sys_exit(int return_code){ Exit(); /* for debugging */label: goto label; /* endless loop */}

void _ttywrch(int ch){char tempch = ch; #ifdef USE_SERIAL_PORT sendchar( &tempch ); #else WriteC( &tempch ); #endif }

__value_in_regs struct __initial_stackheap __user_initial_stackheap( unsigned R0, unsigned SP, unsigned R2, unsigned SL){ struct __initial_stackheap config; config.heap_base = (unsigned int)&bottom_of_heap; // defined in heap.s // placed by scatterfile config.stack_base = SP; // inherit sp from the execution environment return config;}

/*Below is an equivalent example assembler version of __user_initial_stackheap

It will be entered with the value of the stackpointer in r1 (as set in init.s), this does not need to be changed and so can be passed unmodified out of the function.

IMPORT bottom_of_heap EXPORT __user_initial_stackheap

__user_initial_stackheap

Page 156: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

ROMコードの記述

6-22 Copyright © 1999-2001 ARM Limited. All rights reserved. ARM DUI0056DJ-00

LDR r0,=bottom_of_heap MOV pc,lr */

例 6-6 のコードは、単にポーリングされる ARM Integrator ボードの RS232 シリアルドライバを実装しています。このコードは、8データビット、パリティなし、1ストップビットを使用するシリアルポート Aに 9600ボーで単一文字を出力します。このポートは、sendchar()を呼び出す前に init_serial_A()で初期化します。ボードから出

力される文字を監視するには、NULLモデムケーブルを使用して Integratorのシリアルポート Aを RS232端末または PCを実行する端末エミュレータに接続します。

例例例例 6-6 serial.c

#include "intgrt.h" #include "uart.h"

extern struct uart uart0; #define UART0_DR uart0.dr #define UART0_RSR uart0.dr #define UART0_ECR uart0.ecr #define UART0_LCRH uart0.lcrh #define UART0_LCRM uart0.lcrm #define UART0_LCRL uart0.lcrl #define UART0_CR uart0.cr #define UART0_FR uart0.fr #define UART0_IIR uart0.iir #define UART0_ICR uart0.iir void init_serial_A(void) { /* First set the correct baud rate and word length */ UART0_LCRL = LCRL_Baud_38400; // LCRL and LCRM writes _MUST_ // be performed before the LCRH UART0_LCRM = LCRM_Baud_38400; // write as LCRH generates the // write strobe to transfer the UART0_LCRH = LCRH_Word_Length_8 | // data. LCRH_Fifo_Enabled; //

/* Now enable the serial port */ UART0_CR = CR_UART_Enable; // Enable UART0 with no interrupts}

Page 157: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

ROMコードの記述

ARM DUI0056DJ-00 Copyright © 1999-2001 ARM Limited. All rights reserved. 6-23

void sendchar( char *ch ){ while (UART0_FR & FR_TX_Fifo_Full) ; if (*ch == '\n') // Replace line feed with '\r' *ch = '\r'; UART0_DR = *ch; // Transmit next character}

6.5.4 サンプルのビルドサンプルのビルドサンプルのビルドサンプルのビルド

上記のサンプルは以下のいずれかを使用してビルドできます。

• CodeWarrior IDEのプロジェクトファイル

• バッチファイル

• コマンドライン

CodeWarrior IDEの使用の使用の使用の使用

このサンプルを CodeWarrior IDEからビルドするには、付属の embedプロジェクトを

ロードし、Target=EmbeddedScatterを選択します。

これによって以下が作成されます。

• デバッガ(AXDまたは armsd)にロードする ELFデバッグイメージ(embed.axf)

• ARM Integrator ボードのメモリへのダウンロードに適したバイナリ ROM イメージ(embed.bin)

コマンドラインの使用コマンドラインの使用コマンドラインの使用コマンドラインの使用

このサンプルをコマンドラインからビルドするには、build_b.batを実行するか、以

下のステップに従って下さい。

1. 初期化コードをアセンブルします。

armasm -g vectors.sarmasm -g stack.sarmasm -g heap.sarmasm -g init.s

2. 以下のコマンドを使用して、サンプル mainと新しい再対象化ファイルretarget.c、ならびにオプションで serial.cをコンパイルします。

armcc -c -g -O1 main.c -DEMBEDDEDarmcc -c -g -O1 retarget.carmcc -c -g -O1 serial.c -I..\include

Page 158: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

ROMコードの記述

6-24 Copyright © 1999-2001 ARM Limited. All rights reserved. ARM DUI0056DJ-00

上記において:

-D シンボル EMBEDDEDを定義するようにコンパイラに指示します。

-I インクルードファイルを探す場所をコンパイラに指示します。

serial.cの使用はオプションです。出力を Integratorボードのシリアルポートに渡したい場合には、この行を残しておいて下さい。

3. 以下のコマンドを(全部を 1行で)使用して、イメージをリンクさせます。

armlink vectors.o init.o main.o retarget.o serial.o stack.o heap.o -scatter scat_b.scf -o embed.axf -entry 0x0 -info totals -info unused

上記において:

-entry リセットベクタを固有のエントリポイントとして定義します。

-o 出力ファイルを指定します。

-info totals

各オブジェクトファイルのコードサイズとデータサイズ、ならびに各タイプのコードまたはデータの合計サイズに関する情報を出力するようにリンカに通知します。

4. fromELFユーティリティを実行し、イメージのプレーンバイナリバージョンを生成します。

fromelf embed.axf -bin -o embed.bin

上記において:

-bin ヘッダのないバイナリ出力イメージを指定します。

5. ARMulatorを使用してイメージをテストするか、開発ボードに ROMイメージをダウンロードして実行します。

• armsdの場合には以下を使用します。

getfile embed.bin 0x0readsyms embed.axf

• AXDの場合には以下を選択します。

[File] → [Load Memory From File] を選択し、ロードアドレスを 0x0 に設

定した embed.binを指定します。

[File]→ [Load Debug Symbols]を選択し、embed.axfを指定します。

Page 159: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

ROMコードの記述

ARM DUI0056DJ-00 Copyright © 1999-2001 ARM Limited. All rights reserved. 6-25

6.6 分散ローディングと再マッピングの使用分散ローディングと再マッピングの使用分散ローディングと再マッピングの使用分散ローディングと再マッピングの使用

このセクションでは、P. 6-14「アドレス 0への ROMイメージのロード」で示したアプリケーションを、より複雑な分散ローディングアプリケーションに変換する方法を説明します。このサンプルでは、メモリの再マッピングによって、アプリケーション起動後に ROM領域と RAM領域を交換します。

このサンプルコードは、install_directory\Examples\Embedded に収録されて

います。

6.6.1 メモリマップメモリマップメモリマップメモリマップ

図 6-5は以下を示しています。

• FLASH を 0x24000000 に固定します。FLASH のエイリアスコピーがリセット時に 0x0に配置されます。

• 再マッピングの後、32ビット RAMが 0x0に配置され、例外ベクタを保持します。

図図図図 6-5 再マッピングのメモリマップ再マッピングのメモリマップ再マッピングのメモリマップ再マッピングのメモリマップ

6.6.2 分散ロード記述ファイル分散ロード記述ファイル分散ロード記述ファイル分散ロード記述ファイル

P. 6-26例 6-7が示す分散ロード記述ファイルは、1つのロード領域(FLASH)と 5つの実行領域を定義します。

• FLASH(0x24000000)は、全ての読み出し専用コードおよびデータを保持します。

Page 160: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

ROMコードの記述

6-26 Copyright © 1999-2001 ARM Limited. All rights reserved. ARM DUI0056DJ-00

• 32ビット RAM(0x0)は、vectors.oからのベクタテーブルを保持します。

• HEAP(RW/ZIデータのすぐ上)はヒープの開始位置です。

• STACKS(0x40000)はスタックの最上位です。

• UART0(0x16000000)はメモリマップ I/Oを保持します。

例例例例 6-7 scat_c.scf

FLASH 0x24000000 0x4000000 ; The load region starts at 0x24000000 and has ; a maximum size of 0x4000000 bytes.{ FLASH 0x24000000 0x4000000 ; The load and execution addresses are the same. ; Execution region size is less than 0x4000000. { init.o (Init, +First) ; The initialization code is placed first. * (+RO) ; All other RO code and data are placed next. } ; Library code also goes here.

32bitRAM 0x0000 ; RAM starts at address 0x0. { vectors.o (Vect, +First) ; The vector table is placed first in RAM. * (+RW,+ZI) ; All other RW and ZI regions go after vectors. }

HEAP +0 UNINIT ; The heap is not zero-initialized. ; The +0 specification means that the heap { ; starts immediately after RW and ZI regions. heap.o (+ZI) ; A symbol in heap.o is used set the heap base. }

STACKS 0x40000 UNINIT ; The stack is not zero-initialized. { ; The top of stack address is set absolutely. stack.o (+ZI) ; A symbol in stack.o is used to set the } ; top of stack.

UART0 0x16000000 UNINIT ; The UART is not zero-initialized. { ; The address is specified absolutely. uart.o (+ZI) ; The symbols in uart.o are used to reserve the } ; memory-mapped I/O.}

このプログラムのコードとデータは、0x24000000 に常駐するフラッシュ内に配置さ

れます。リセット時、ハードウェアによってフラッシュのエイリアスコピーがアドレス 0x0に再マップされます。プログラムの実行は、init.s内の AREA Initで開始されます。+Firstオプションは、このコードを最初にイメージ内に配置するために使用

されています。リセット後、init.s の最初のいくつかの命令が 32 ビット RAM をアドレス 0x0 に再マップします。ARM Integrator ボードはそれ自身のフラッシュをこの方法で再マップします。

Page 161: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

ROMコードの記述

ARM DUI0056DJ-00 Copyright © 1999-2001 ARM Limited. All rights reserved. 6-27

ROコードのほとんどはフラッシュから実行されます。ROの実行アドレスは、そのロードアドレス(0x24000000)と同じであるため、移動させる必要はありません。

32bitRAMには高速オンチップ32ビットSSRAMなどを使用することが考えられます。高速 RAM はスタックと、高速で実行する必要があるコードに使用するのが一般的で

す。例外ベクタ(vectors.s 内の AREA Vect)は、実行速度を上げるためにフラッシュから 0x0にある 32ビット RAM実行領域に再配置されます。この領域内には Vect

コードが最初に配置されます。RWデータは、このベクタコードの後にフラッシュから32bitRAM実行領域に再配置されます。ZIデータは RWデータの上に作成されます。

6.6.3 初期化コード初期化コード初期化コード初期化コード

例 6-8は、ROM/RAMの再マッピングを実行する init.s内のコードを示しています。

例例例例 6-8 ROM/RAMの再マッピングの再マッピングの再マッピングの再マッピング

; --- Set up if ROM/RAM remapping required GBLL ROM_RAM_REMAPROM_RAM_REMAP SETL {TRUE} ; change to {FALSE} if remapping not required

...

; --- Perform ROM/RAM remapping, if required IF :DEF: ROM_RAM_REMAP

; On reset, an aliased copy of ROM is at 0x0.; Continue execution from 'real' ROM rather than aliased copy LDR pc, =Instruct_2 Instruct_2

; Remap by setting Remap bit of the CM_ctl register LDR r1, =CM_ctl_reg LDR r0, [r1] ORR r0, r0, #Remap_bit STR r0, [r1] ; RAM is now at 0x0.; The exception vectors (in vectors.s) must be copied from ROM to the RAM; The copying is done later by the C library code inside __main

Cライブラリに含まれる初期化コードは、ゼロ初期化エリアを作成する前に、ROおよび RW実行領域をそれぞれのロードアドレスから実行アドレスにコピーします(P. 6-14「アドレス 0への ROMイメージのロード」参照)。

Page 162: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

ROMコードの記述

6-28 Copyright © 1999-2001 ARM Limited. All rights reserved. ARM DUI0056DJ-00

6.6.4 サンプルのビルドサンプルのビルドサンプルのビルドサンプルのビルド

上記のサンプルをビルドするには、以下のどちらかの方法を使用します。

• CodeWarrior IDEを使用して付属の embed.mcpプロジェクトを開き、

EmbeddedScatterRemapビルドターゲットを選択する。

• build_c.batバッチファイルを使用するか、以下を含むメークファイルを使用

する(インデントが挿入された行は、その上の 1行からの継続行です)。

armasm -g vectors.sarmasm -g -PD "ROM_RAM_REMAP SETL {TRUE}" init.sarmasm -g stack.sarmasm -g heap.sREM Use the following two lines to build without using the serial port. armcc -c -g -O1 main.c -DEMBEDDED -DROM_RAM_REMAParmcc -c -g -O1 retarget.cREM Use the following two lines to build using the serial port. REM armcc -c -g -O1 main.c -DEMBEDDED -DROM_RAM_REMAP -DUSE_SERIAL_PORTREM armcc -c -g -O1 retarget.c -DUSE_SERIAL_PORTarmcc -c -g -O1 uart.c -I..\includearmcc -c -g -O1 serial.c -I..\includearmlink vectors.o init.o main.o retarget.o uart.o serial.o stack.o heap.o -scatter scat_c.scf -o embed.axf -entry 0x24000000 -info totals -info unusedfromelf embed.axf -bin -o embed.bin

上記から以下が作成されます。

• ARMデバッガにロードする ELFデバッグイメージ(embed.axf)

• ARM 開発ボードの RAM またはフラッシュメモリへのダウンロードに適したバイナリ ROMイメージ(embed.bin)

ARM Integratorボードのフラッシュメモリにイメージをダウンロードし、そこでデバッグする詳しい方法については、readme.txtファイルを参照して下さい。

6.6.5 再マッピングのその他のサンプル再マッピングのその他のサンプル再マッピングのその他のサンプル再マッピングのその他のサンプル

install_directory\Examples\Embedded\ledflash ディレクトリには、ARMIntegratorボード上で動作する単純な割り込み駆動型LEFフラッシャが含まれています。このフラッシャは、ROM/RAMの再マッピングと分散ローディングを使用します。

このサンプルをビルドするためのバッチファイル(build.bat)と CodeWarrior IDE

プロジェクトファイル(ledflash.mcp)が付属しています。このコードをフラッシュ

にダウンロードする方法を記載したファイルも、上記のディレクトリに収録されています。

P. 6-37「メモリマップ I/Oを使用した分散ローディング」を参照して下さい。

Page 163: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

ROMコードの記述

ARM DUI0056DJ-00 Copyright © 1999-2001 ARM Limited. All rights reserved. 6-29

6.7 セミホステッドアプリケーションの割り込み処理セミホステッドアプリケーションの割り込み処理セミホステッドアプリケーションの割り込み処理セミホステッドアプリケーションの割り込み処理

このセクションでは、組み込みアプリケーションに最適な、割り込み駆動タイマに基づいた基本ペリフェラル仕様(RPS)について説明します。main()関数は 2つの RPS

タイマを初期化し、始動させます。

タイマが時間切れになると、割り込みが生成されます。割り込みは int_handler.c

内で処理されます。このコードは単にフラグをセットし、割り込みをクリアします。割り込みフラグは下方のエンドレスループでチェックされます。フラグがセットされていればメッセージが表示され、その後クリアされます。

6.7.1 メモリマップメモリマップメモリマップメモリマップ

リンカコマンドオプションにはメモリ指定オプションがないため、デフォルトの値が使用されます。コード領域は 0x08000 で開始されます。RW データ領域と ZI データ領域は、このコード領域の後にシーケンシャルに配置されます。スタック最上部は

0x80000です。

6.7.2 サンプルのビルドサンプルのビルドサンプルのビルドサンプルのビルド

このサンプルは、以下のどちらかの方法でビルドできます。

• 付属の rps_irq.mcpプロジェクトを CodeWarrior IDEにロードする。

• バッチファイル(build_a.bat)または以下を含むメークファイルを使用する。

armcc -c -g -O1 main.c -I..\includearmcc -c -g -O1 int_handler.c -I..\includearmlink main.o int_handler.o -o rps_irq.axf -info totals

6.7.3 サンプルコードサンプルコードサンプルコードサンプルコード

P. 6-30 例 6-9 はそれだけでコンパイルしてリンクし、セミホスティング環境で実行されます。Install_Handler は割り込みベクタをインストールするために呼び出され

ます。P. 6-33例 6-10のコードは、割り込みハンドラを示しています。このサンプルは、セミホスティングを行わない組み込みアプリケーションとしてビルドできます(P. 6-34「組み込みアプリケーションの割り込み処理」参照)。

Page 164: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

ROMコードの記述

6-30 Copyright © 1999-2001 ARM Limited. All rights reserved. ARM DUI0056DJ-00

例例例例 6-9 rps_irqのサンプルコードのサンプルコードのサンプルコードのサンプルコードmain.c

/*** Copyright (C) ARM Limited, 2000. All rights reserved.*/

#include <stdio.h> #include <stdlib.h> #include "stand_i.h" #include "rpsarmul.h" /* EITHER: to use with the ARMulator *//* #include "intgrt.h" */ /* OR: to use with the Integrator board */

int IntCT1 = 0;int IntCT2 = 0;int Count = 0; #ifndef EMBEDDEDextern IRQ_Handler(void);unsigned *irqvec = (unsigned *)0x18;unsigned Install_Handler (unsigned routine, unsigned *vector)

/* Updates contents of 'vector' to contain branch instruction */ /* to reach 'routine' from 'vector'. Function return value is */ /* original contents of 'vector'. */ /* NB: 'Routine' must be within range of 32MB from 'vector'. */

{ unsigned vec, oldvec; vec = ((routine - (unsigned)vector - 0x8)>>2); if (vec & 0xff000000) { printf ("Installation of Handler failed"); exit(1); } vec = 0xea000000 | vec; oldvec = *vector; *vector = vec; return (oldvec);} #endif

/* Enabling and disabling interrupts Interrupts are enabled or disabled by reading the cpsr flags and updating bit 7.

These functions work only in a privileged mode, because the control bits of the cpsr and spsr cannot be changed while in User mode.

Page 165: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

ROMコードの記述

ARM DUI0056DJ-00 Copyright © 1999-2001 ARM Limited. All rights reserved. 6-31

*/

__inline void enable_IRQ(void){ int tmp; __asm { MRS tmp, CPSR BIC tmp, tmp, #0x80 MSR CPSR_c, tmp }}

__inline void disable_IRQ(void){ int tmp; __asm { MRS tmp, CPSR ORR tmp, tmp, #0x80 MSR CPSR_c, tmp }} #ifdef EMBEDDEDextern void init_serial_A(void); #endif

int main(void){ #ifdef EMBEDDED #pragma import(__use_no_semihosting_swi) // ensure no functions that use // semihosting SWIs are linked in // from the C library #ifdef USE_SERIAL_PORT init_serial_A(); // Initialize serial port A #endif #endif

printf("RPS Timer Interrupt Example\n"); #ifdef EMBEDDED #ifdef ROM_RAM_REMAP printf("Embedded (ROM/RAM remap, no SWIs) version\n"); #else printf("Embedded (ROM at 0x0, no SWIs) version\n"); #endif #else Install_Handler ((unsigned)IRQ_Handler, irqvec);

Page 166: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

ROMコードの記述

6-32 Copyright © 1999-2001 ARM Limited. All rights reserved. ARM DUI0056DJ-00

printf("Normal (RAM at 0x8000, semihosting) version\n\n"); #endif printf("Initializing...\n");

enable_IRQ();

*IRQEnableClear = ~0; // Clear/disable all interrupts *Timer1Control = 0; // Disable counters by clearing the control bytes *Timer2Control = 0; *Timer1Clear = 0 ; // Clear counter/timer interrupts by writing to *Timer2Clear = 0 ; // the clear register - any data will work *Timer1Load = FAST_LOAD; // Load counter values *Timer2Load = MED_FAST_LOAD;

*Timer1Control = (TimerEnable | // Enable the Timer TimerPeriodic | // Periodic Timer producing interrupt TimerPrescale8 ); // Set Maximum Prescale - 8 bits

*Timer2Control = (TimerEnable | // Enable the Timer TimerPeriodic | // Periodic Timer producing interrupt TimerPrescale8 ); // Set Maximum Prescale - 8 bits

*IRQEnableSet = IRQTimer1 | IRQTimer2; // Enable the counter timer interrupts

printf("Running...\n");

IntCT1 = 0; // Clear CT 1 Flag IntCT2 = 0; // Clear CT 2 Flag Count = 0;

while ( Count < 20 ) { if (IntCT1 != 0) // Timer 1 Interrupt occurred { Count++; printf("IntCT1\n"); IntCT1 = 0; // Reset the Timer 1 Interrupt Flag } if (IntCT2 != 0) // Timer 2 Interrupt occurred { Count++; printf("IntCT2\n"); IntCT2 = 0; // Reset the Timer 2 Interrupt Flag } }

disable_IRQ();}

Page 167: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

ROMコードの記述

ARM DUI0056DJ-00 Copyright © 1999-2001 ARM Limited. All rights reserved. 6-33

例例例例 6-10 サンプルコードサンプルコードサンプルコードサンプルコード int_handler.c

/*** Copyright (C) ARM Limited, 2000. All rights reserved.*/ #include "stand_i.h" #include "rpsarmul.h" /* EITHER: to use with the ARMulator */ /* #include "intgrt.h" */ /* OR: to use with the Integrator board */

/******************************************************************************* IRQHandler ** ** This function handles IRQ interrupts. In this example, these may come from ** Timer 1 or Timer 2. ** ** This handler simply clears the interrupt and sets corresponding flags. ** These flags are then checked by the main application. ** ********************************************************************************/

void __irq IRQ_Handler(void){ unsigned status;

status = *IRQStatus; /* Deal with source of interrupt */ /* RMC source definitions used for CT1, CT2 */

if (status & IRQTimer1) { *Timer1Clear = 0;/* clear the interrupt */ IntCT1++; /* set the flag */ } else if (status & IRQTimer2) { *Timer2Clear = 0;/* clear the interrupt */ IntCT2++; /* set the flag */ } }

Page 168: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

ROMコードの記述

6-34 Copyright © 1999-2001 ARM Limited. All rights reserved. ARM DUI0056DJ-00

6.8 組み込みアプリケーションの割り込み処理組み込みアプリケーションの割り込み処理組み込みアプリケーションの割り込み処理組み込みアプリケーションの割り込み処理

このセクションでは、P. 6-29「セミホステッドアプリケーションの割り込み処理」にあるアプリケーションを組み込み可能なアプリケーションに変換する方法を説明します。このアプリケーションの変換には以下のファイルが必要です。

vectors.s このファイルには例外ベクタと例外ハンドラが含まれています。このサ

ンプルでは ROMを 0x0に固定しています。

init.s ROM/RAMの再マッピングを(必要に応じて)実行し、各モードのスタックポインタと割り込みを初期化し、Cライブラリ内の __mainに分岐し

ます。__mainのCライブラリコードが結果的にmain()を呼び出します。

このサンプルでは ROM/RAM の再マッピングは使用していません。再

マッピングを記述した分散ロードサンプルファイルは、

install_directory\Examples\embedded\rps_irq に収録されて

います。

retarget.c このファイルは低レベル I/Oの再対象化レイヤを実装します。一般的に、このファイルにはターゲット依存の実装を記述します。このサンプルでは、fputc()、ferror()、_sys_exit()、_ttywrch()、

__user_initial_stackheap()を実装します。

#define USE_SERIAL_PORTは、ARM開発(PID)ボードのシリアルポートから文字を出力するコードを選択します。

serial.c このファイルは、ポーリングされるARM Integartorボードの単純なRS232

シリアルドライバを実装しています。このコードは、8データビット、パリティなし、1ストップビットを使用するシリアルポート Aに 9600ボーで単一文字を出力します。

uart.cファイルは、uart0構造をインスタンス生成します。分散ロー

ディングファイルは、この構造をペリフェラルレジスタに配置します。I/O 構造の定義については、P. 6-37「メモリマップ I/O を使用した分散ローディング」を参照して下さい。

heap.s このファイルはシンボル bottom_of_heapをエクスポートします。

stack.s このファイルはシンボル top_of_stacksをエクスポートします。

セミホスティング SWIを使用する関数が Cライブラリからリンクされないように、#pragma import(__use_no_semihosting_swi)が main()から参照されます。

Page 169: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

ROMコードの記述

ARM DUI0056DJ-00 Copyright © 1999-2001 ARM Limited. All rights reserved. 6-35

6.8.1 メモリマップメモリマップメモリマップメモリマップ

この分散ロード記述ファイルでは、1つのロード領域、FLASH、5つの実行領域を定義しています。

FLASH プログラム全体が ROMに配置されます。ROコードが FLASHから実行

されます。FLASHの実行アドレスは、そのロードアドレス(0x24000000)

と同じであるため、移動させる必要はありません。

32bitRAM 例外ベクタテーブル vectors.sは 0x0にある RAMに置く必要があるため、+First コマンドを使用してこれを最初にイメージ内に配置しま

す。RWデータは、0x0のベクタコードの上に、FLASHから 32bitRAM

に配置されます。ZIデータは RWデータの上の RAMで初期化されます。

このサンプルでは ROM/RAM の再マッピングは使用していません。再

マッピングを記述した分散ロードサンプルファイルは、

install_directory\Examples\Embedded\rps_irq に収録されて

います。

HEAP ヒープは、変数に使用されるメモリの終わりに配置されます。オブジェ

クトheap.oは、ヒープベースの設定に使用されるシンボルを保持します。

STACKS スタックの最上部は 0x40000です。オブジェクト stack.oは、スタッ

クの最上部の設定に使用されるシンボルを保持します。

UART0 メモリマップ I/Oは 0x16000000にあります。オブジェクト uart.oは、

メモリマップ I/O の予約に使用されるシンボルを保持します。このメモリはゼロ初期化されません。

6.8.2 サンプルのビルドサンプルのビルドサンプルのビルドサンプルのビルド

このサンプルをビルドするには、バッチファイル build_c.bat、ターゲットに

EmbedScatterを設定した CodeWarrior IDEプロジェクトファイル rps_irq.mcp、ある

いは以下を含むメークファイルを使用します(インデントが挿入されている行は、その上の 1行からの継続行であることを意味します)。

armasm -g vectors.sarmasm -g -PD "ROM_RAM_REMAP SETL {TRUE}" init.sarmasm -g stack.sarmasm -g heap.s

REM Use the following lines to build without using the serial port. armcc -c -g -O1 main.c -I..\include -DEMBEDDED -DROM_RAM_REMAParmcc -c -g -O1 retarget.c

REM Use the following lines to build using the serial port. REM armcc -c -g -O1 main.c -I..\include -DEMBEDDED -DROM_RAM_REMAPREM -DUSE_SERIAL_PORTREM armcc -c -g -O1 retarget.c -DUSE_SERIAL_PORT

Page 170: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

ROMコードの記述

6-36 Copyright © 1999-2001 ARM Limited. All rights reserved. ARM DUI0056DJ-00

armcc -c -g -O1 uart.c -I..\includearmcc -c -g -O1 serial.c -I..\includearmcc -c -g -O1 int_handler.c -I..\includearmlink vectors.o init.o main.o retarget.o uart.o serial.o stack.o heap.o int_handler.o -scatter scat_c.scf -o rps_irq.axf -entry 0x24000000 -info totals -info unusedfromelf rps_irq.axf -bin -o rps_irq.bin

6.8.3 分散ロード記述ファイル分散ロード記述ファイル分散ロード記述ファイル分散ロード記述ファイル

以下は分散ロード記述ファイルを示しています。

FLASH 0x24000000 0x4000000{ FLASH 0x24000000 0x4000000 { init.o (Init, +First) * (+RO) }

32bitRAM 0x0000 { vectors.o (Vect, +First) * (+RW,+ZI) }

HEAP +0 UNINIT { heap.o (+ZI) } STACKS 0x40000 UNINIT { stack.o (+ZI) } UART0 0x16000000 UNINIT { uart.o (+ZI) }}

6.8.4 サンプルコードサンプルコードサンプルコードサンプルコード

この再対象化コードは、P. 6-14「アドレス 0への ROMイメージのロード」で使用したコードと同じです。このソースは

install_directory\Examples\Embedded\rps_irqに収録されています。

Page 171: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

ROMコードの記述

ARM DUI0056DJ-00 Copyright © 1999-2001 ARM Limited. All rights reserved. 6-37

6.9 メモリマップメモリマップメモリマップメモリマップ I/Oを使用した分散ローディングを使用した分散ローディングを使用した分散ローディングを使用した分散ローディング

ほとんどの ARM組み込みシステムでは、ペリフェラルはメモリ内の特定のアドレスに配置します。通常、ペリフェラル内のメモリマップレジスタには C 変数を使用してアクセスする必要があります。コードを記述する際は、レジスタのサイズとアドレスだけではなく、メモリ内におけるアライメントにも注意する必要があります。

16 ビットまたは 8 ビットのペリフェラルを使用する場合には、ペリフェラルレジスタをワード境界整列させることを推奨します。リトルエンディアンシステムの場合、ペリフェラルデータバスはARMデータバスの最下位ビットに直接接続することが可能であり、ペリフェラルデータバスを ARM データバスの上位ビットに多重化(または重

複)させる必要はありません。ビッグエンディアンシステムの場合、ペリフェラルデータバスは ARMデータバスの最上位ビットに直接接続することが可能であり、ペリフェラルデータバスを ARMデータバスの下位ビットに多重化(または重複)させる必要はありません。

AMBA™ APB ブリッジはこの手法を利用してブリッジ設計を簡素化しています。したがって、ワード境界配列のアドレスだけ(バイト、ハーフワードあるいはワードの転送)を使用すれば、読み出しを行ってもペリフェラルに接続されないビットのガーベッジが読み出されるだけです。

6.9.1 ポインタを使用したポインタを使用したポインタを使用したポインタを使用した I/Oへのアクセスへのアクセスへのアクセスへのアクセス

メモリマップ変数を実装する最も簡単な方法は、固定アドレスへのポインタを使用する方法です。メモリがハードウェアなどの外的要因によって変化する可能性がある場合には、volatileとラベル付けする必要があります。例:

volatile unsigned *port = (unsigned int *) 0x40000000;

ポート上のデータには以下によってアクセスできます。

*port = value; /* write to port */ value = *port; /* read from port */

volatileを使用することにより、コンパイラはメモリアクセスを最適化してしまわず

にこれを必ず実行します。そのアクセスがループ内にあり、変数が volatileでなかっ

た場合には、そのメモリアドレスの読み出しが 1度だけ行われます。

このアプローチは 8ビット、16ビットあるいは 32ビットのレジスタへのアクセスに使用できますが、そのサイズに適切なタイプの変数を宣言する必要があります。32 ビットレジスタには int、16ビットには short、8ビットには charを使用します。これ

により、コンパイラは LDR/STR、LDRH/STRH、LDRB/STRB の中で正しい単一ロード /

ストア命令を生成します。

Page 172: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

ROMコードの記述

6-38 Copyright © 1999-2001 ARM Limited. All rights reserved. ARM DUI0056DJ-00

また、メモリマップレジスタは必ず適切なアドレス境界で配置する必要があります。アライメントは、全てワード境界配列にするか、それぞれの自然サイズの境界で配列させます。16 ビットレジスタの自然サイズは、ハーフワードアドレスです。ARM では、サイズに関係なく全てのレジスタをワード境界整列させることを推奨しています(P. 6-39「配列または構造の使用」参照)。

#defineを使用するとコードを簡素化することができます。例えば、例 6-11のソースコードからは、例 6-12のインタリーブされたコードが生成されます。

例例例例 6-11

#define PORTBASE 0x40000000 /* Counter/Timer Base */ #define PortLoad ((volatile unsigned int *) PORTBASE) /* 32 bits */ #define PortValue ((volatile unsigned short *)(PORTBASE + 0x04)) /* 16 bits */ #define PortClear ((volatile unsigned char *)(PORTBASE + 0x08)) /* 8 bits */

void init_regs(void){ unsigned int int_val; unsigned short short_val; unsigned char char_val; *PortLoad = (unsigned int) 0xF00FF00F; int_val = *PortLoad; *PortValue = (unsigned short) 0x0000; short_val = *PortValue; *PortClear = (unsigned char) 0x1F; char_val = *PortClear;}

例例例例 6-12 -Sとととと -fsを使用したコンパイラからの出力フラグメントを使用したコンパイラからの出力フラグメントを使用したコンパイラからの出力フラグメントを使用したコンパイラからの出力フラグメント

AREA ||.text||, CODE, READONLY

init_regs PROC;;;7 {;;;8 unsigned int int_val;;;;9 unsigned short short_val;;;;10 unsigned char char_val;;;;11 *PortLoad = (unsigned int) 0xF00FF00F;000000 e59f1024 LDR r1,|L1.44|000004 e3a00440 MOV r0,#0x40000000000008 e5801000 STR r1,[r0,#0];;;12 int_val = *PortLoad;00000c e5901000 LDR r1,[r0,#0];;;13 *PortValue = (unsigned short) 0x0000;

Page 173: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

ROMコードの記述

ARM DUI0056DJ-00 Copyright © 1999-2001 ARM Limited. All rights reserved. 6-39

000010 e3a01000 MOV r1,#0000014 e1c010b4 STRH r1,[r0,#4];;;14 short_val = *PortValue;000018 e1d010b4 LDRH r1,[r0,#4];;;15 *PortClear = (unsigned char) 0x1F;00001c e3a0101f MOV r1,#0x1f000020 e5c01008 STRB r1,[r0,#8];;;16 char_val = *PortClear;000024 e5d00008 LDRB r0,[r0,#8];;;17 }000028 e1a0f00e MOV pc,lr |L1.44|00002c f00ff00f DCD 0xf00ff00f ENDP END

6.9.2 ユニオンの使用ユニオンの使用ユニオンの使用ユニオンの使用

例 6-13は、ワード境界で整列し、16ビットメモリにマップされたペリフェラルレジスタへのアクセス方法を示しています。このサンプルではワードアライメントを強制するために unionを使用しています。

例例例例 6-13

/* header file */typedef union { short x; int pad; } X; /* force alignment of type X to */ /* the natural alignment of int */static X *const device = (X *) 0xffff00c0; /* use of static and const enable*/ /* the compiler to better */ /* optimize the code */

/* C file */void f(void) { device[2].x = 3; } /* write the value 3 to the */ /* third 16-bit value of device */

6.9.3 配列または構造の使用配列または構造の使用配列または構造の使用配列または構造の使用

以下のサンプルは、配列または構造を使用したペリフェラルレジスタへのアクセス方法を示しています。

ショート配列の使用ショート配列の使用ショート配列の使用ショート配列の使用

16ビットアライメントの 16ビットペリフェラルレジスタにアクセスするには、以下のように記述することができます。

volatile unsigned short u16_IORegs[20];

Page 174: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

ROMコードの記述

6-40 Copyright © 1999-2001 ARM Limited. All rights reserved. ARM DUI0056DJ-00

リトルエンディアンシステムの場合、この方法はペリフェラルコントローラがペリフェラルデータバスを ARM データバスの上位部分(D31 ~ D16)にルーティングし、アクセスするアドレスによってその下位部分(D15~ D0)にもルーティングできる場合に機能します。この多重化ロジックが設計に組み込まれているかどうかをチェックする必要があります(標準 ARM APBブリッジはこれをサポートしていません)。

構造の使用構造の使用構造の使用構造の使用

配列ではなく構造を使用すると、以下のような利点があります。

• 描写的な名前を使用できる(保守が容易で、かつ理解しやすい)。

• 様々なレジスタ幅を使用できる。

パディングは、コンパイラが自動的に追加するパディングではなく、明示的に挿入する必要があります。例:

struct PortRegs { unsigned short ctrlreg; /* offset 0 */ unsigned short dummy1; unsigned short datareg; /* offset 4 */ unsigned short dummy2; unsigned int data32reg; /* offset 8 */} iospace;

x = iospace.ctrlreg;iospace.ctrlreg = newval;

注注注注

ペリフェラルの位置には、__packed 構造(非境界整列メンバの使用が許され、内部パディングがない構造)または C ビットフィールドを使用してアクセスしないようにして下さい。これは、コンパイラによって実行されるメモリアクセスの値とタイプを制御することが不可能なためです。

したがってコードが移植不可能となり、望ましくない副作用が発生し、期待通りに機能しなくなる可能性があります。ペリフェラルへのアクセスには、アーキテクチャ上で定義されている int、short、charなどのタイプをそれぞれの自然なアライメントで明示的に使用する方法を推奨します。

構造構造構造構造 /配列へのポインタの使用配列へのポインタの使用配列へのポインタの使用配列へのポインタの使用

struct PortRegs { unsigned short ctrlreg; /* offset 0 */ unsigned short dummy1; unsigned short datareg; /* offset 4 */ unsigned short dummy2; unsigned int data32reg; /* offset 8 */};

Page 175: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

ROMコードの記述

ARM DUI0056DJ-00 Copyright © 1999-2001 ARM Limited. All rights reserved. 6-41

volatile struct PortRegs *iospace = (struct PortRegs *)0x40000000;x = iospace->ctrlreg;iospace->ctrlreg = newval;

ポインタはローカルでもグローバルでも可能です。関数呼び出し後のベースポインタの再配置を防ぐためにグローバルポインタを使用したい場合には、構造への定数ポインタ iospaceの定義を以下に変更します。

volatile struct PortRegs * const iospace = (struct PortRegs *)0x40000000;

6.9.4 分散ローディングの使用分散ローディングの使用分散ローディングの使用分散ローディングの使用

変数、配列あるいは構造は、それが含まれているファイル内で宣言する必要があります。コンパイルすると、このファイルのオブジェクトコードにはデータだけが含まれます。このデータは、ARM分散ローディング機能を使用して指定アドレスに配置することができます。メモリマップ内の特定の位置に領域を配置する場合には、この方法を推奨します。

例えば、変数、配列あるいは構造の宣言を含むファイル iovar.cを作成します。例:

volatile unsigned short u16_IORegs[20];

または

struct{ volatile unsigned reg1; volatile unsigned reg2;} mem_mapped_reg;

サンプルファイルのコードを含む scatter.scf という名前の分散ロード記述ファイ

ルを作成します。

例例例例 6-14 サンプルファイルサンプルファイルサンプルファイルサンプルファイル

ALL 0x8000 ; one load region ALL at 0x8000{ ALL 0x8000 ; by default, everything goes into this region { * (+RO,+RW,+ZI) }

IO 0x40000000 UNINIT ; register variables go here ; initial zeros are not written {

Page 176: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

ROMコードの記述

6-42 Copyright © 1999-2001 ARM Limited. All rights reserved. ARM DUI0056DJ-00

iovar.o (+ZI) ; a single module is selected by name }}

この分散ロード記述ファイルを、-scatter scatter.scfコマンドラインオプショ

ンを使用してリンカに指定する必要があります。記述ファイル内の UNINIT キーワー

ドは、アプリケーションのリセット時に ZI領域をゼロで初期化しないことを示します。リセット時に、ペリフェラルレジスタにゼロを書き込ませたい場合は、UNINIT キー

ワードを省略して下さい。この分散ロード記述ファイルから作成されるイメージには 2つの異なる領域(ALLおよび IO)が含まれます。iovar.o(配列または構造を含んだ

ファイル)からのゼロ初期化エリアは、0x40000000の IOエリアに出力されます。他

のオブジェクトファイルからの全てのコードエリア(RO)とデータエリア(RW およ

び ZI)は、0x8000で始まる ALL領域に出力されます。

複数の変数グループ(複数のメモリマップレジスタセット)がある場合は、各変数グループを別々の実行領域として定義する必要があります(しかし、全てが 1 つのロード領域内に配置される可能性もあります)。各変数グループは別々のモジュール内で定義する必要があります。

分散ロード記述ファイルの使用には以下のような利点があります。

• 使用するデバイス、コード、データに対して選択された全ての(ターゲット固有の)絶対アドレスが 1つのファイル内に保存されるため、保守が容易である。

• メモリマップを変更する場合(ペリフェラルを移動させる場合など)にも、既存オブジェクトを再リンクさせるだけでプロジェクト全体を再ビルドする必要がない。

分散ローディングの詳細については、ADSリンカ /ユーティリティガイドを参照して下さい。C および C++ によるコードセクションとデータセクションの指定方法については、ADSコンパイラ /ライブラリガイドの「プラグマ」のセクションを参照して下さい。

6.9.5 コードの効率性コードの効率性コードの効率性コードの効率性

通常、ARMコンパイラはロード /ストア命令のベースレジスタ +イミディエートオフセットフィールドを使用して、構造メンバまたは特定の配列要素へのアクセスをコンパイルします。

ARM 命令セットのワードまたはバイトの LDR/STR は 4K バイト範囲を使用しますが、LDRH/STRHはこれよりも少ない256バイトのイミディエートオフセットを使用します。

Thumb命令セットのアドレシング範囲は、ARM命令よりも大幅に制限されます。Thumbの LDR/STRは 32ワード範囲、LDRH/STRHは 32ハーフワード範囲、LDRB/STRBは 32

バイト範囲を使用します。したがって関連するペリフェラルレジスタはできる限り隣

Page 177: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

ROMコードの記述

ARM DUI0056DJ-00 Copyright © 1999-2001 ARM Limited. All rights reserved. 6-43

接してグループ化する必要があります。一般的には、コンパイラはベースレジスタを使用することにより、配列要素または構造メンバへのアクセスに必要な命令数を最小限に抑えます。

I/O空間全体に 1つの大きな C構造 /配列を使用するか、より小さなペリフェラルごとの構造を使用するかは選択できます。効率性の点でもほとんど違いはありません。大きな構造は、ベースポインタが 4K バイト範囲に及び(ワード / バイトアクセスの場合)、I/O空間全体が 4KB未満の ARMコードを使用する場合などに効果的です。ペリフェラルごとの小さな構造は保守が容易です。

Page 178: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

ROMコードの記述

6-44 Copyright © 1999-2001 ARM Limited. All rights reserved. ARM DUI0056DJ-00

6.10 トラブルシューティングトラブルシューティングトラブルシューティングトラブルシューティング

このセクションでは、以下の一般的な問題の解決策について説明します。

• リンカエラー __semihosting_swi_guard

• $top_of_memoryの設定

• ベクタテーブルコードの消失:P. 6-45

• 分散ローディング記述ファイルに関するエラー:P. 6-45

6.10.1 リンカエラーリンカエラーリンカエラーリンカエラー __semihosting_swi_guard

リンカは __semihosting_swi_guardが多重定義されていることを通知します。

原因原因原因原因

リンカがANSI Cライブラリから関数のセミホスティング実装をロードしたことが原因です。このエラーメッセージは、#pragma import(__use_no_semihosting_swi)

でセミホスティング保護シンボルをインポートしたか、または C保護関数__use_no_semihosting_swi()を呼び出したときに、同時にセミホスティングを使

用するライブラリ関数も呼び出したときに発行されます。

解決策解決策解決策解決策

この問題は以下のどちらかの方法で解決できます。

• 使用する実装でセミホステッド関数を再定義する。これにより、Cライブラリバージョンの代わりに新しい関数が使用されます。

• デバッグ目的で ROMイメージのアプリケーションバージョンをビルドする場合にのみセミホステッド関数が使用される場合は、ROM イメージをビルドする際にこれらの関数を #ifdefでコメントアウトする。

セミホスティングを使用する関数を探すには、-verbose -errors file.txtにリ

ンクさせ、__I_use_semihosting_swiが出現する出力ログファイルを検索します。

6.10.2 $top_of_memoryの設定の設定の設定の設定

デバッガ内部変数 $top_of_memory は、最上位の書き込み可能アドレスがリモート

ターゲットのメモリマップ内に存在することをデバッガに通知します。デフォルトでは、このアドレスはスタックとヒープの配置に使用されます。$top_of_memoryのデ

フォルト値は 0x80000です。

ボードが異なればメモリマップも異なる可能性があるため、$top_of_memoryは使用

するボードの RAM の最上位アドレスを加算したアドレスに変更する必要があります。この作業はアプリケーションの実行前に行う必要があり、これを行わなければデータアボートまたはコードのクラッシュが発生する可能性があります。

Page 179: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

ROMコードの記述

ARM DUI0056DJ-00 Copyright © 1999-2001 ARM Limited. All rights reserved. 6-45

拡張していない Integratorコアモジュールの場合は、$top_of_memoryを 0x40000に

設定します。

使用するボードに他の DRAMモジュールが接続されている場合には、$top_of_memoryを正しく変更する必要があります。

$top_of_memoryはMulti-ICEとEmbeddedICEだけに適用されます。AngelとARMulator

には適用されません。(Angel のメモリの最上位は移植時にハードコーディングされており、ARMulatorのスタックベースは config.ファイルによって決定されます。)

6.10.3 ベクタテーブルコードの消失ベクタテーブルコードの消失ベクタテーブルコードの消失ベクタテーブルコードの消失

デフォルトでは、リンカは実行されることのないコードセクションを、または参照されることのないデータを、イメージから削除します。どのセクションが削除されたかを確認するには、-info unusedオプションを使用してリンクを行います。

ベクタテーブルが不意に削除されることのないように以下のステップに従って下さい。

1. アセンブラディレクティブ ENTRY を使用して全てのエントリポイントをマーキングします。Cライブラリのエントリポイントは __main()にあります。

2. コマンドラインオプション -entry を使用して、エントリポイントの 1 つをイメージのエントリポイントとして指定します。一意のエントリポイントが指定されていない場合、リンカは以下の警告メッセージを生成します。

Image does not have an entry point. (Not specified or not set due to multiple choices).

組み込みイメージには以下のリンクオプションを推奨します。

armlink obj1.o obj2.o -scatter scat.scf -info unused -entry 0x0 -o prog.axf

6.10.4 分散ローディング記述ファイルに関するエラー分散ローディング記述ファイルに関するエラー分散ローディング記述ファイルに関するエラー分散ローディング記述ファイルに関するエラー

分散ローディング記述ファイルを使用してリンクを試みたときにエラーが発生した場合は、ビルドプロセスを簡素化して徐々に複雑になるようにしてみて下さい。以下に、効果があると思われるいくつかの方法を示します。

__user_initial_stackheap()の再対象化の再対象化の再対象化の再対象化

分散ローディングを使用するときは、__user_initial_stackheap()

を再実装する必要があります。この関数が正しく再実装され、新しいモジュールがコードとリンクされることを確認して下さい。手始めとしてExamples ディレクトリに収録されている再実装のサンプルを使用して

下さい。

コードとデータを保持させるに十分な領域を作成するコードとデータを保持させるに十分な領域を作成するコードとデータを保持させるに十分な領域を作成するコードとデータを保持させるに十分な領域を作成する

分散ローディング記述ファイル内で最大サイズを指定する場合は、そのサイズが関連コードまたはデータを保持させるに十分な大きさであることを確認して下さい。

Page 180: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

ROMコードの記述

6-46 Copyright © 1999-2001 ARM Limited. All rights reserved. ARM DUI0056DJ-00

各領域の絶対アドレスを指定する場合は、領域がオーバラップしないように注意する必要があります。

記述ファイル内で記述ファイル内で記述ファイル内で記述ファイル内で ANY指定子を使用する指定子を使用する指定子を使用する指定子を使用する

非常に独特な名前を使用してコードとデータを割り当てる場合は、その指定とマッチしないコードが配置されないことがあります。マッチしないコードとデータも全て配置するには、*または ANYを指定して下さい。

Page 181: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

ROMコードの記述

ARM DUI0056DJ-00 Copyright © 1999-2001 ARM Limited. All rights reserved. 6-47

6.11 コードサイズとデータサイズの測定コードサイズとデータサイズの測定コードサイズとデータサイズの測定コードサイズとデータサイズの測定

コードサイズを測定する場合は、リンクしたイメージのサイズやオブジェクトモジュールのサイズでは測定しないで下さい。これらにはバイナリデータの一部ではないシンボリックな情報が含まれています。代わりに、以下の armlinkオプションのどちらかを使用して下さい。

-info sizes このオプションを指定すると、イメージを構成する各オブジェク

トファイルまたはライブラリメンバの詳細なコードサイズとデータサイズを見ることができます。

-info totals このオプションを指定すると、イメージを構成する全てのオブ

ジェクトファイルとライブラリメンバのコードサイズとデータサイズの合計を見ることができます。

6.11.1 サイズ情報の解釈サイズ情報の解釈サイズ情報の解釈サイズ情報の解釈

-info sizesオプションと-info totalsオプションを指定して得られる情報は、以

下に分類できます。

• コード(または読み出し専用)セグメント

• データ(または読み出し /書き込み)セグメント

• デバッグデータ

コード(または読み出し専用)セグメントコード(または読み出し専用)セグメントコード(または読み出し専用)セグメントコード(または読み出し専用)セグメント

code size コードセグメント内にある全てのデータを除いたコードのサイズです。

RO data コンパイラによってコードセグメント内にインクルードされた読み出し

専用データのサイズです。

このデータには以下が含まれます。

• コードによってアクセスされる変数のアドレス

• 浮動小数点イミディエート値

• レジスタに直接ロードできないイミディエート値

• 短いインラインストリング

• ROデータ内の長いインラインストリングのアドレス

Page 182: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

ROMコードの記述

6-48 Copyright © 1999-2001 ARM Limited. All rights reserved. ARM DUI0056DJ-00

データ(または読み出しデータ(または読み出しデータ(または読み出しデータ(または読み出し /書き込み)セグメント書き込み)セグメント書き込み)セグメント書き込み)セグメント

RW data 読み出し /書き込みデータのサイズです。読み出し /書き込みが行われるデータで、初期値も含まれます。Read-write data は、表示された

RAMの量をランタイムに使用しますが、イメージの起動時に RAMにコピーされる初期値を保持する幾分かの ROMも必要とします。

ZI data イメージの起動時にゼロ初期化される読み出し / 書き込みデータのサイズです。

通常、この中には Cソースコード内で初期化されない配列が含まれます。ゼロ初期化されるデータは、表示された量の RAM をランタイムに占有

しますが、ROM内の空間は必要としません。

デバッグデータデバッグデータデバッグデータデバッグデータ

debug data デバッグするデータのサイズを通知します。

6.11.2 ROMおよびおよびおよびおよび RAM要件の計算要件の計算要件の計算要件の計算

リンカは、データとコードに必要となる ROMと RAMの量を以下のように計算します。

ROM Code size + RO data + RW data

RAM RW Data + ZI data.

これに加え、スタックとヒープに使用される RAMを見越しておく必要があります。

複雑なシステムでは、コードセグメントの一部(または全部)をランタイムに ROMから RAM にダウンロードしなければならない場合があります。これによってシステム

RAM要件が増えますが、例えば RAMアクセス時間が ROMアクセス時間よりも速く、システムの実行速度が重要な場合には、この作業が必要となります。

Page 183: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

ARM DUI0056DJ-00 Copyright © 1999-2001 ARM Limited. All rights reserved. 7-1

第 7章キャッシュと密結合メモリキャッシュと密結合メモリキャッシュと密結合メモリキャッシュと密結合メモリ

本章では、キャッシュ搭載プロセッサの初期化について説明します。また、密結合メモリを搭載したプロセッサと、キャッシュ搭載プロセッサの ARMulator モデルについても解説します。本章は以下のセクションから構成されています。

• キャッシュおよび密結合メモリについて:P. 7-2

• システム制御コプロセッサ:P. 7-4

• メモリ保護ユニット:P. 7-5

• PUの構成:P. 7-7

• メモリ管理ユニット:P. 7-12

• MMUの構成:P. 7-16

• 密結合メモリ:P. 7-19

ARM Architecture Reference Manual と、使用するプロセッサのテクニカルリファレンスマニュアルも参照して下さい。

Page 184: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

キャッシュと密結合メモリ

7-2 Copyright © 1999-2001 ARM Limited. All rights reserved. ARM DUI0056DJ-00

7.1 キャッシュおよび密結合メモリについてキャッシュおよび密結合メモリについてキャッシュおよび密結合メモリについてキャッシュおよび密結合メモリについて

現在のほとんどのプロセッサコアは、オフチップメモリシステムよりもはるかに高速で命令とデータを処理することができます。キャッシュと密結合メモリ(TCM)は、外部メモリがコアよりも狭く遅い場合、または両方ともが狭く遅い場合に、システムのパフォーマンスを向上させる手段となります。

キャッシュと TCMは、プロセッサと密接に接続された小さな高速メモリです。これらのメモリによって以下が可能となります。

• 帯域が狭い、または速度が遅いオフチップメモリがあっても、システムパフォーマンスを上げられる。

• オフチップメモリへのアクセスを減らすことにより、システムの総電力消費量を軽減できる。

注注注注

オフチップメモリがコアと同じくらい速く、32 ビット幅である場合には、一般的にはキャッシュ不在のコアを選択した方が効果的です。

7.1.1 キャッシュについてキャッシュについてキャッシュについてキャッシュについて

キャッシュはメモリ位置の内容のコピーを保持します。一般的に、これらの内容は最近からロードされたメモリ位置を示します。これらのコピーは自動的にオフチップメモリに優先して使用されます。

キャッシュの使用には、キャッシングされるメモリ位置が再度使用される場合にのみ効果があります。実システムでは、以下などにキャッシュを使用するのが極めて一般的です。

• 命令ループ

• 頻繁に参照されるデータ

キャッシュの動作はプログラマからは認識できません。しかし、コアを初期化して、どのオフチップメモリ位置をキャッシュするかを指定する必要があります。

7.1.2 密結合メモリについて密結合メモリについて密結合メモリについて密結合メモリについて

イネーブルされていれば、TCMはオフチップメモリの一部のエリアの代わりに使用されます。

キャッシュと比較して、TCMには以下のような利点があります。

• ダイサイズが半分で済む。

• リアルタイムパフォーマンスを正確に予測できる。

TCM を利用するには、システムソフトウェアを記述するときに TCM を考慮しておく必要があります。例えば、以下を TCM内に配置することが考えられます。

• 割り込み処理コード

• スタックなど、頻繁に変化するデータ

Page 185: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

キャッシュと密結合メモリ

ARM DUI0056DJ-00 Copyright © 1999-2001 ARM Limited. All rights reserved. 7-3

詳細については、P. 7-19「密結合メモリ」を参照して下さい。

7.1.3 キャッシュおよび密結合メモリのモデルキャッシュおよび密結合メモリのモデルキャッシュおよび密結合メモリのモデルキャッシュおよび密結合メモリのモデル

キャッシュまたは TCM を使用するプロセッサの ARMulator モデルには、そのキャッシュまたは TCMのモデルが含まれます。

モデルキャッシュまたはモデル TCMを初期化する場合は、ハードウェアをプログラムするのと全く同じように PU モデルまたは MMU モデルをプログラムすることができます。

ARMulator Pagetableモデルモデルモデルモデル

さらに、ARMualtor はモデルキャッシュまたはモデル TCM を自動的に初期化できる

Pagetableモデルをインクルードします(ADSデバッグターゲットガイドの「ARMulatorの基本」参照)。

ここで、以下のどの方法でも取ることができます。

• オペレーティングシステムを記述する場合を除き、開発作業全体を通してこのPagetableモデルを使用する。ユーザモードプログラムを記述する場合は、この方法を推奨します。

• PUまたはMMUのプログラミングコードを一から記述する。

• 開発の初期ステージでは Pagetableモデルを使用し、後で PUまたはMMUのプログラミングコードを記述する。

キャッシュとキャッシュとキャッシュとキャッシュと TCMのののの ARMulaotrモデルのデフォルト初期状態モデルのデフォルト初期状態モデルのデフォルト初期状態モデルのデフォルト初期状態

初期化時:

• キャッシュの ARMulatorモデルが Pgetableモデルによってイネーブルされます。

• TCMの ARMulatorモデルがディセーブルされます。

これらのデフォルトは、peripherals.amiファイルで変更することができます(ADS

デバッグターゲットガイド参照)。

7.1.4 キャッシュパフォーマンスキャッシュパフォーマンスキャッシュパフォーマンスキャッシュパフォーマンス

メインメモリの一部が 32ビット幅で、コアと同じくらい速い場合には、キャッシュを使用することでシステムパフォーマンスが低下する可能性があります。

ほとんどのシステムでは、コアよりも遅く、32 ビットよりも幅の狭いメモリが使用されています。

Page 186: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

キャッシュと密結合メモリ

7-4 Copyright © 1999-2001 ARM Limited. All rights reserved. ARM DUI0056DJ-00

7.2 システム制御コプロセッサシステム制御コプロセッサシステム制御コプロセッサシステム制御コプロセッサ

CP15 はシステム制御コプロセッサです。コアと、キャッシュまたは TCM を構成するには、CP15のレジスタに書き込む必要があります。

CP15のレジスタは、MCR命令とMRC命令を使用することによってのみアクセスできます(これらの命令については、ADSアセンブラガイドの ARM命令の章を参照して下さい)。

CP15のレジスタに関する詳しい説明については、ARM Architecture Reference Manualと、使用しているプロセッサのテクニカルリファレンスマニュアルを参照して下さい。

注注注注

システムにMMUが存在する場合は、MMUをイネーブルする前にページテーブルをメモリに書き込む必要があります(P. 7-16「MMUの構成」参照)。

Page 187: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

キャッシュと密結合メモリ

ARM DUI0056DJ-00 Copyright © 1999-2001 ARM Limited. All rights reserved. 7-5

7.3 メモリ保護ユニットメモリ保護ユニットメモリ保護ユニットメモリ保護ユニット

保護ユニット(PU)はメモリを領域に分割します。各領域には以下を指定することができます。

サイズサイズサイズサイズ 通常は、4KB~ 4GBです。

ベースアドレスベースアドレスベースアドレスベースアドレス

領域は、そのサイズの倍数となるメモリ境界で開始する必要があります。

アクセスパーミッションアクセスパーミッションアクセスパーミッションアクセスパーミッション

例えば、ユーザモードからのみの読み出しアクセスを許可する領域をマーキングすることができます。

PU がイネーブルされている場合、PU は定義されている領域以外のアドレスへのアクセスをアボートします。

7.3.1 ハーバードアーキテクチャハーバードアーキテクチャハーバードアーキテクチャハーバードアーキテクチャ

ARMのキャッシュ搭載ハーバードコアでは命令キャッシュとデータキャッシュが分かれていますが、同じバスを使用して外部メモリにアクセスします。データと命令に使用されるメモリ領域のプロパティは個々に定義することができます。

PUをイネーブルする前に、以下を定義する必要があります。

• 命令に使用する少なくとも 1つのメモリ領域

• データに使用する少なくとも 1つのメモリ領域

これらの領域には同じメモリ領域を定義することが可能です。

7.3.2 フォン・ノイマンアーキテクチャフォン・ノイマンアーキテクチャフォン・ノイマンアーキテクチャフォン・ノイマンアーキテクチャ

フォン・ノイマン型のコアは同一バスでデータと命令にアクセスします。

PUをイネーブルする前に少なくとも 1つのメモリ領域を定義する必要があります。

Page 188: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

キャッシュと密結合メモリ

7-6 Copyright © 1999-2001 ARM Limited. All rights reserved. ARM DUI0056DJ-00

7.3.3 領域のオーバラップ領域のオーバラップ領域のオーバラップ領域のオーバラップ

オーバラップするメモリ保護領域を定義することができます。複数のメモリ領域が同じメモリをマップする場合、PUは最上位番号の領域を使用してメモリへのアクセスを制御します。

図 7-1は、メモリ領域の例を示しています。この例では、バックグラウンド領域が全体のアドレス空間を占めています。フォアグラウンド領域がバックグランド領域にオーバラップしています。

図図図図 7-1 メモリ領域の例メモリ領域の例メモリ領域の例メモリ領域の例

注注注注

コード内のリテラルプールに含まれているデータへのアクセスを可能にするため、命令領域には対応するデータ領域が割り当てられます。

Page 189: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

キャッシュと密結合メモリ

ARM DUI0056DJ-00 Copyright © 1999-2001 ARM Limited. All rights reserved. 7-7

7.4 PUの構成の構成の構成の構成

PUを構成するには、以下を行う必要があります。

1. 保護領域の開始アドレスとサイズを定義し、これらをイネーブルします。このためには、CP15のコプロセッサレジスタ c6、システム制御コプロセッサへの書き込みを行う必要があります(P. 7-8「保護領域のアドレスとサイズの設定、各領域のイネーブル」参照)。

2. 各領域にキャッシュ可能属性とバッファ可能属性を設定します。このためには、CP15レジスタ c2および c3に書き込みを行います(P. 7-9「領域のキャッシュ可能 /バッファ可能フラグの設定」参照)。

3. 各領域のアクセスパーミッションを設定します。このためには、CP15レジスタ c5への書き込みを行います(P. 7-10「領域のアクセスパーミッションの設定」参照)。

4. キャッシュと PUをイネーブルします。このためには、CP15レジスタ c1への書き込みを行います(P. 7-11「コア動作の構成」参照)。

注注注注

ARMulatorを使用していれば、この作業は Pagetableモデルが自動的に行います(P. 7-3「キャッシュおよび密結合メモリのモデル」および ADS デバッグターゲットガイドの「ARMualtorの基本」参照)。

注注注注

コンフィギュレーション情報はコアによって異なります。使用するコアのテクニカルリファレンスマニュアルを参照して下さい。

以下の例では、一般的なプログラミング方法を示します。これらの方法を全てのコアに適用できるわけではありません。

Page 190: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

キャッシュと密結合メモリ

7-8 Copyright © 1999-2001 ARM Limited. All rights reserved. ARM DUI0056DJ-00

7.4.1 保護領域のアドレスとサイズの設定、各領域のイネーブル保護領域のアドレスとサイズの設定、各領域のイネーブル保護領域のアドレスとサイズの設定、各領域のイネーブル保護領域のアドレスとサイズの設定、各領域のイネーブル

例 7-1では、保護領域のアドレスとサイズを設定します。

注注注注

保護領域をイネーブルしていても、PUをイネーブルしない限りは効果がありません。

例例例例 7-1 保護領域の設定保護領域の設定保護領域の設定保護領域の設定

LDR r0,=0xFFFF801D ; define ROM with base address 0xFFFF8000, size 32KB, enabled MCR p15,0,r0,c6,c1,0 ; apply this definition to data region 1 MCR p15,0,r0,c6,c1,1 ; apply the same definition to instruction region 1

LDR r0,=0xB0000039 ; define Peripherals with base address 0xB0000000, size 512MB, enabled MCR p15,0,r0,c6,c2,0 ; apply this definition to data region 2

LDR r0,=0x4000001F ; define Data with base address 0x40000000, size 64KB, enabled MCR p15,0,r0,c6,c3,0 ; apply this definition to data region 3

MOV r0,#0x1D ; define Code with base address 0x0, size 32KB, enabled MCR p15,0,r0,c6,c4,0 ; apply this definition to data region 4 MCR p15,0,r0,c6,c4,1 ; apply the same definition to instruction region 4

コプロセッサレジスタコプロセッサレジスタコプロセッサレジスタコプロセッサレジスタ 6

c6 は、領域のベースとサイズに使用するレジスタを選択する際に、最初のコプロセッサレジスタとして使用します。

領域は次のコプロセッサレジスタ番号、上記の例では c1~ c4、を使用して選択します。

r0などの ARMレジスタ内の値は以下を保持します。

• ビット [31:12] -ベースアドレス

• ビット [11:6]- ゼロ

• ビット [5:1] -領域サイズ(詳細については、使用するプロセッサのテクニカルリファレンスマニュアルを参照して下さい)

• ビット [0]がセットされると、領域がイネーブルされます。

Opcode2

Opcode2は、データ領域と命令領域を別々にもつコアだけに使用します(詳細については、使用するコアのテクニカルリファレンスマニュアルを参照して下さい)。

プロセッサが別々のデータ領域と命令領域をサポートしていない場合は、Opcode2にゼロを設定する必要があります。これらがサポートされている場合は、データ領域に 0を、命令領域に 1を設定します。

Page 191: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

キャッシュと密結合メモリ

ARM DUI0056DJ-00 Copyright © 1999-2001 ARM Limited. All rights reserved. 7-9

7.4.2 領域のキャッシュ可能領域のキャッシュ可能領域のキャッシュ可能領域のキャッシュ可能 /バッファ可能フラグの設定バッファ可能フラグの設定バッファ可能フラグの設定バッファ可能フラグの設定

CP15 のコプロセッサレジスタ c2 は、領域キャッシュ可能フラグレジスタです。CP15のコプロセッサレジスタ c3 は、領域バッファ可能フラグレジスタです。例 7-2 では、各データ領域のキャッシュ可能フラグとバッファ可能フラグを設定します。

領域をキャッシュ可能に設定したい場合:

• その領域からのロードを行うと、キャッシュが検索されます。項目が検出されると、これがキャッシュからロードされます。項目が検出されない場合は、要求されているアドレスを含むキャッシュ行全体がロードされます。未使用のキャッシュ行がない限り、他のいくつかのキャッシュ行がキャッシュから払い出されます。

• その領域への保存を行うと、キャッシュが検索されます。項目が検出されると、その保存はキャッシュに対して行われます。項目が検出されない場合は、その保存がメモリに対して行われます。

バッファ可能フラグの厳密な効果は状況によって異なります(詳細については、使用しているプロセッサのテクニカルリファレンスマニュアルを参照して下さい)。

CP15レジスタ c2のビット [7:0]は、キャッシュ可能フラグを保持します。命令領域とデータ領域の選択には Opcode 2が使用されます。

CP15レジスタ c3のビット [7:0]は、バッファ可能フラグを保持します。バッファ可能フラグはデータ領域だけにしか使用できないため、Opcode 2 には 0 を設定する必要があります。

Operand2は、データ領域または命令領域を指定します。

例例例例 7-2 キャッシュ可能キャッシュ可能キャッシュ可能キャッシュ可能 /バッファ可能フラグの設定バッファ可能フラグの設定バッファ可能フラグの設定バッファ可能フラグの設定

MOV r0,#2_00011010 ; set data regions 1, 3 and 4 as cacheable, all others noncacheable MCR p15,0,r0,c2,c0,0

MOV r0,#2_00010010 ; set instruction regions 1 and 4 as cacheable, all others noncacheable MCR p15,0,r0,c2,c0,1

MOV r0,#2_00001000 ; set data region 3 as write bufferable, all others nonbufferable MCR p15,0,r0,c3,c0,0

Page 192: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

キャッシュと密結合メモリ

7-10 Copyright © 1999-2001 ARM Limited. All rights reserved. ARM DUI0056DJ-00

7.4.3 領域のアクセスパーミッションの設定領域のアクセスパーミッションの設定領域のアクセスパーミッションの設定領域のアクセスパーミッションの設定

CP15 のコプロセッサレジスタ c5 は、領域アクセスパーミッションレジスタです。例7-3では、領域のアクセスパーミッションを設定します。

Operand2は、データ領域または命令領域を指定します。

例例例例 7-3 アクセスパーミッションの設定アクセスパーミッションの設定アクセスパーミッションの設定アクセスパーミッションの設定

MOV r0,#2_1111111100 ; set data region 1, 2, 3 and 4 as full access MCR p15,0,r0,c5,c0,0

MOV r0,#2_1000001000 ; set instruction region 1 and 4 as: MCR p15,0,r0,c5,c0,1 ; Privileged Mode, full access; User Mode, read only

表7-1および表7-2は、アクセスパーミッションレジスタのビットの意味を示しています。

注注注注

プロセッサによっては、各領域に 4ビットが割り当てられる場合があります(詳細については、使用するプロセッサのテクニカルリファレンスマニュアルを参照して下さい)。

表表表表 7-1 領域のビットマッピングスキーム領域のビットマッピングスキーム領域のビットマッピングスキーム領域のビットマッピングスキーム

レジスタビットレジスタビットレジスタビットレジスタビット 機能機能機能機能

[15:14] エリア 7のアクセスパーミッションビット [1:0]

[13:12] エリア 6のアクセスパーミッションビット [1:0]

[11:10] エリア 5のアクセスパーミッションビット [1:0]

... ...

表表表表 7-2 領域のアクセスパーミッションビットの定義領域のアクセスパーミッションビットの定義領域のアクセスパーミッションビットの定義領域のアクセスパーミッションビットの定義

ビットビットビットビット [1:0] 意味意味意味意味

00 アクセス不可

01 特権モードからのアクセスのみ可

10 特権モードからは全てのアクセスが可、ユーザモードからは読み出しのみ可

11 全てのアクセスが可能

Page 193: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

キャッシュと密結合メモリ

ARM DUI0056DJ-00 Copyright © 1999-2001 ARM Limited. All rights reserved. 7-11

7.4.4 コア動作の構成コア動作の構成コア動作の構成コア動作の構成

CP15 のコプロセッサレジスタ c1 は、コアコンフィギュレーションレジスタです。c1の内容は、読み出し -修正 -書き込みサイクルを使用して変更する必要があります。例7-4では、コアを構成して PUをイネーブルします。

例例例例 7-4 コア動作の構成(コア動作の構成(コア動作の構成(コア動作の構成(ARM940Tのみ)のみ)のみ)のみ)

MRC p15,0,r0,c1,c0,0 ; read core configuration register ORR r0,r0,#0xC0000000 ; set asynchronous clocks and not fastbus mode ORR r0,r0,#0x1000 ; enable instruction cache ORR r0,r0,#0x5 ; enable data cache and PU MCR p15,0,r0,c1,c0,0 ; write modified value to core configuration register

表7-3は、ARM940Tにおけるコアコンフィギュレーションビットの意味を示しています。

注注注注

コアコンフィギュレーションレジスタの情報は、コアによって異なります。詳細については、使用するプロセッサのテクニカルリファレンスマニュアルを参照して下さい。

表表表表 7-3 コアコンフィギュレーションレジスタ(コアコンフィギュレーションレジスタ(コアコンフィギュレーションレジスタ(コアコンフィギュレーションレジスタ(ARM940T))))

レジスタビットレジスタビットレジスタビットレジスタビット 機能機能機能機能

[31] 非同期クロッキング選択ビット(iA)

[30] nFastBus選択ビット(nF)

[29:14] 予約ビット(ゼロを設定するか、読み出し -修正 -書き込みを使用します)

[13] 代替ベクタ選択ビット(V)

[12] 命令キャッシュイネーブルフラグ(I)

[11:8] 予約ビット(ゼロを設定するか、読み出し -修正 -書き込みを使用します)

[7] ビッグエンディアンビット(E)

[6:3] 予約ビット(ゼロを設定するか、読み出し -修正 -書き込みを使用します)

[2] データキャッシュイネーブルフラグ(D)

[1] 予約ビット(ゼロを設定するか、読み出し -修正 -書き込みを使用します)

[0] PUイネーブルビット(P)

Page 194: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

キャッシュと密結合メモリ

7-12 Copyright © 1999-2001 ARM Limited. All rights reserved. ARM DUI0056DJ-00

7.5 メモリ管理ユニットメモリ管理ユニットメモリ管理ユニットメモリ管理ユニット

メモリ管理ユニット(MMU)は:

• 仮想アドレスを物理アドレスに変換します。

• メモリアクセスパーミッションを制御します。

MMUをディセーブルしていると、外部アドレスバスが変換されていないアドレスを出力します。

MMUは PUよりもはるかに柔軟です。MMUは以下を行うことが可能です。

• 緻密に細分したメモリシステムの制御を渡す。

• メモリをランタイムに再配置する。

MMU を使用することにより、要求ページ仮想メモリシステムを実装することができます。

7.5.1 仮想アドレスから物理アドレスへのマッピング仮想アドレスから物理アドレスへのマッピング仮想アドレスから物理アドレスへのマッピング仮想アドレスから物理アドレスへのマッピング

ARM プロセッサによって生成されるアドレスは仮想アドレスです。MMU がイネーブルされていれば、MMU がこれらの仮想アドレスを物理アドレスに変換します。したがって、物理アドレスが別の位置にあるときは、指定した仮想アドレスのコードまたはデータにアクセスすることができます。この原理は、アドレスマップに矛盾を生じさせる複数のプロセスにメモリを割り当てるといった、様々な目的に利用することができます。

変換テーブルはメインメモリにストアされます。アドレス変換を保持する他、このテーブルは以下を制御するフィールドを保持します。

• 各領域のメモリアクセスパーミッション(P. 7-14「メモリアクセスパーミッションとドメイン」参照)

• 領域へのアクセスがキャッシュ可能またはバッファ可能かを制御するフラグ(P. 7-15「キャッシュ可能 /バッファ可能フラグ」参照)

P. 7-13 図 7-2 は、仮想アドレスから物理アドレスへのマッピングに適用される原理を示しています。

Page 195: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

キャッシュと密結合メモリ

ARM DUI0056DJ-00 Copyright © 1999-2001 ARM Limited. All rights reserved. 7-13

図図図図 7-2 仮想アドレスから物理アドレスへのマッピング仮想アドレスから物理アドレスへのマッピング仮想アドレスから物理アドレスへのマッピング仮想アドレスから物理アドレスへのマッピング

警告警告警告警告

キャッシュは仮想アドレスを保持します。異なるプロセスにあるメモリエリアを共有させる目的がない限りは、異なるプロセスからの仮想アドレスが同じ物理アドレスにマッピングされないように注意して下さい。

変換テーブルの詳細については、ARM Architecture Reference Manual と、使用しているプロセッサのテクニカルリファレンスマニュアルを参照して下さい。

Page 196: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

キャッシュと密結合メモリ

7-14 Copyright © 1999-2001 ARM Limited. All rights reserved. ARM DUI0056DJ-00

7.5.2 メモリアクセスパーミッションとドメインメモリアクセスパーミッションとドメインメモリアクセスパーミッションとドメインメモリアクセスパーミッションとドメイン

変換テーブルには、アクセスパーミッションフィールドとドメインフィールドがあります。

全部で 16 ドメインがあり、変換テーブルで定義された各領域は、対応するドメインフィールドに指定されたドメインによって制御されます。

各ドメインには、CP15のドメインアクセス制御レジスタ内の 2ビットが割り当てられます。これらのビットの値により、ドメインに属する領域へのアクセス試行には以下のいずれかが適用されます。

• 変換テーブル内に設定されたパーミッションが許可する場合にのみ許可される。

• ドメイン障害を生成する。

• 変換テーブル内に設定されたパーミッションに関係なく許可される。

プロセッサがメモリアクセス要求を生成すると、MMUは以下のようにパーミッションをチェックします。

1. MMUが変換テーブル内のドメイン番号を検索します。

2. ステップ 1で検出したドメイン番号を使用して、MMUはドメインアクセス制御レジスタ内のドメインに対するドメインアクセスパーミッションをチェックします。

3. ドメインアクセス制御レジスタ内で検出した値に基づき、MMUは以下のいずれかを行います。

• そのアクセスを無条件で許可する。

• そのアクセスを無条件で拒否する。

• 変換テーブル内でその領域へのアクセスパーミッションをチェックする。

このシステムにより、コンテキストを容易に変更することができます。各アプリケーションに対し、オペレーティングシステムは以下を行うことができます。

• 異なるメモリアクセスへのフリーアクセスまたは制限アクセスを許可するか、アクセスを許可しない。

• ドメインアクセス制御レジスタ内の 1つのエントリを変更することにより、多数の領域へのアクセスパーミッションを同時に変更する。

Page 197: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

キャッシュと密結合メモリ

ARM DUI0056DJ-00 Copyright © 1999-2001 ARM Limited. All rights reserved. 7-15

7.5.3 キャッシュ可能キャッシュ可能キャッシュ可能キャッシュ可能 /バッファ可能フラグバッファ可能フラグバッファ可能フラグバッファ可能フラグ

変換テーブルは、キャッシュ可能フラグとバッファ可能フラグも保持します。

ある領域をキャッシュ可能領域として設定する場合:

• その領域からのロードを実行すると、キャッシュが検索されます。対象項目が検出されると、その項目がキャッシュからロードされます。項目が検出されない場合は、要求されたアドレスを含むキャッシュ行全体がロードされます。未使用のキャッシュ行がない限り、他のいくつかのキャッシュ行がキャッシュから払い出されます。

• その領域へのストアを実行すると、キャッシュが検索されます。対象項目が検出されると、その項目がキャッシュにストアされます。項目が検出されない場合、そのストアはメモリに対して行われます。

バッファ可能フラグの厳密な効果はプロセッサによって異なります(詳細については、使用しているプロセッサのテクニカルリファレンスマニュアルを参照して下さい)。

一般的に以下のような特定のメモリエリアのキャッシングまたはバッファリングは避けた方が無難です。

• メモリマップ I/O

• ランダムにアクセスする大きな配列

詳細については、ARM Architecture Reference Manual と、使用しているプロセッサのテクニカルリファレンスマニュアルを参照して下さい。

Page 198: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

キャッシュと密結合メモリ

7-16 Copyright © 1999-2001 ARM Limited. All rights reserved. ARM DUI0056DJ-00

7.6 MMUの構成の構成の構成の構成

MMUを構成するには、以下を行う必要があります。

1. メモリ内に変換テーブルを作成する。変換テーブルは以下を保持します。

• 仮想 -物理変換

• キャッシュ可能フラグとバッファ可能フラグ

• ドメイン番号

• アクセスパーミッション

P. 7-17「変換テーブルの作成」を参照して下さい。

2. 変換テーブルの位置を、CP15レジスタ c2にストアします(P. 7-17「変換テーブルの位置の設定」参照)。

3. CP15レジスタ c1への書き込みにより、キャッシュとMMUをイネーブルします(P. 7-18「コア動作の構成」参照)。

注注注注

ARMualtor を使用している場合、上記は PageTable モデルが自動的に行います(P. 7-3「キャッシュおよび密結合メモリのモデル」、ADS デバッグターゲットガイドの「ARMualtorの基本」参照)。

以下を行うことを推奨します。

• 変換テーブルのパーミッションを特権モードアクセスのみに設定する。

• 変換テーブルを含む領域に関して、仮想アドレスを同一の物理アドレスにマップする。

7.6.1 プログラム実行中の変換テーブルの変更プログラム実行中の変換テーブルの変更プログラム実行中の変換テーブルの変更プログラム実行中の変換テーブルの変更

変換テーブルは、MMU をディセーブルしなくても変更することができます。変更後は、変換ルックアサイドバッファ(TLB)をフラッシュする必要があります。詳細については、ARM Architecture Reference Manual と、使用しているプロセッサのテクニカルリファレンスマニュアルを参照して下さい。

Page 199: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

キャッシュと密結合メモリ

ARM DUI0056DJ-00 Copyright © 1999-2001 ARM Limited. All rights reserved. 7-17

7.6.2 変換テーブルの作成変換テーブルの作成変換テーブルの作成変換テーブルの作成

例 7-5では、各仮想アドレスを同一の物理アドレスにマップする(これをフラットマッピングと呼びます)変換テーブルを初期化します。ここでは、アドレス 0x000xxxxx

~ 0xFFFxxxxx に 4096 エントリを保持し、全ての領域にフルアクセスできるテーブルを作成します。

例例例例 7-5 フラット変換テーブルフラット変換テーブルフラット変換テーブルフラット変換テーブル

LDR r0,=TTB ; Set start of translation table base (on 16KB boundary) LDR r1, =0xFFF ; Set loop counter for 4096 MOV r2, #2_110000000000 ; Set access permissions for full access (bits 11:10) ORR r2,r2,#2_000111100000 ; Set domain number to 15 (bits 8:5) ORR r2,r2,#2_000000010000 ; Set bit 4 to 1 ORR r2,r2,#2_000000000010 ; Set as 1MB section (bits 1:0) ; All unused bits are 0loop ORR r3,r2,r1,LSL#20 ; Build pattern into empty register STR r3,[r0,r1,LSL#2] ; Use loop counter to create individual table base addresses SUBS r1,r1,#1 ; Decrement loop counter BPL loop ; Loop until r1 goes negative

非フラット変換の設定方法については、P. 7-18「0x0 にある ROM のエイリアスを0xFFF00000に配置する」を参照して下さい。

7.6.3 変換テーブルの位置の設定変換テーブルの位置の設定変換テーブルの位置の設定変換テーブルの位置の設定

例 7-6では、CP15の変換テーブルベースレジスタ(c2)を設定します。

例例例例 7-6 変換テーブルベースの設定変換テーブルベースの設定変換テーブルベースの設定変換テーブルベースの設定

LDR r0,=TTB : Set start of translation table base (on 16KB boundary) MCR p15,0,r0,c2,c2,0 ; Write value to CP15 c2

Page 200: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

キャッシュと密結合メモリ

7-18 Copyright © 1999-2001 ARM Limited. All rights reserved. ARM DUI0056DJ-00

7.6.4 領域のエイリアスの作成領域のエイリアスの作成領域のエイリアスの作成領域のエイリアスの作成

例 7-7は、ROM領域のエイリアスの作成方法を示しています。

例例例例 7-7 0x0にあるにあるにあるにある ROMのエイリアスをのエイリアスをのエイリアスをのエイリアスを 0xFFF00000に配置するに配置するに配置するに配置する

LDR r0,=TTB : Set start of translation table base (on 16KB boundary) LDR r1,=0x0 ; Read first entry in translation table, which points to a 1MB section at 0x0 LDR r2,[r0,r1,LSL#2] ORR r2,r2,#2_1000 ; Set cacheable flag

LDR r1,=0xFFF00000 ; Remap 0x0 to 0xFFF00000 STR r2,[r0,r1,LSL#2]

MOV r0,#0xC0000000 ; Set permissions for domain 15 MCR p15,0,r0,c3,c0,0 ; Write value to CP15 c3

7.6.5 コア動作の構成コア動作の構成コア動作の構成コア動作の構成

例 7-8では、CP15のコア制御レジスタ(c1)内のビットを設定します。

例例例例 7-8 コア制御パラメータの設定(コア制御パラメータの設定(コア制御パラメータの設定(コア制御パラメータの設定(ARM920Tのみ)のみ)のみ)のみ)

MRC p15,0,r0,c1,c0,0 ; Read control register ORR r0,r0,#0xC00000000 ; Set asynchronous clocking mode bits ORR r0,r0,#0x1000 ; Set enable instruction cache bit ORR r0,r0,#0x5 ; Set enable data cache and MMU bits MCR p15,0,r0,c1,c0,0 ; Write to control register

注注注注

コアコンフィギュレーションレジスタの情報はコアによって異なります。詳細については、使用するプロセッサのテクニカルリファレンスマニュアルを参照して下さい。

Page 201: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

キャッシュと密結合メモリ

ARM DUI0056DJ-00 Copyright © 1999-2001 ARM Limited. All rights reserved. 7-19

7.7 密結合メモリ密結合メモリ密結合メモリ密結合メモリ

TCMへのアクセスには、通常のメモリアクセス命令を使用します。TCMにアクセスする命令と、オフチップメモリにアクセスする命令との唯一の違いはアドレスです。

ARM966E-Sなどのいくつかのコアには TCMがあってもキャッシュがありません。

ARM946E-Sなどの他のコアには TCMとキャッシュの両方があります。TCMとキャッシュは同時にイネーブルできますが、一般的には物理メモリの同一領域をマップすることはできません。

次のセクションでは ARM966E-Sのメモリマップについて概説します。この情報はコアによって異なります。詳細については、使用するプロセッサのテクニカルリファレンスマニュアルを参照して下さい。

Page 202: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

キャッシュと密結合メモリ

7-20 Copyright © 1999-2001 ARM Limited. All rights reserved. ARM DUI0056DJ-00

7.7.1 ARM966E-Sのメモリマップのメモリマップのメモリマップのメモリマップ

図 7-3は、ARM966E-Sのメモリマップの例を示しています。

図図図図 7-3 ARM966E-Sのメモリマップのメモリマップのメモリマップのメモリマップ

Page 203: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

キャッシュと密結合メモリ

ARM DUI0056DJ-00 Copyright © 1999-2001 ARM Limited. All rights reserved. 7-21

メモリの複数のエイリアスメモリの複数のエイリアスメモリの複数のエイリアスメモリの複数のエイリアス

ARM966E-S は、TCM 内に最大 64MB の命令メモリと、最大 64MB のデータメモリを保持します。

P. 7-20図 7-3の例では、TCM内に 64KBの命令メモリを実装しています。このメモリは 1024 の異なる位置にアドレス指定することが可能であり、TCM は命令フェッチのビット [25:16]を無視します。

この例では、TCM内にさらに 32KBのデータメモリを実装しています。このメモリは2048 の異なる位置にアドレス指定することが可能であり、TCM はデータアクセスの

ビット [25:15]を無視します。

命令メモリとデータメモリ命令メモリとデータメモリ命令メモリとデータメモリ命令メモリとデータメモリ

命令 TCMとデータ TCMは個々にイネーブルすることができます。

TCMがディセーブルされると、そのアドレス範囲への全てのアクセスがオフチップアクセスとなります。同一アドレスにあるオフチップメモリと TCMは完全に独立しています。

命令TCMへのデータアクセスは可能です。このアクセスが許可される必要があるのは、以下を行うためです。

• リテラルプールの使用

• デバッグ目的でのソフトウェアブレークポイントの設定

• コードのダウンロード

• 自己修正コードの書き込み

データ TCMから命令フェッチを行うことはできません。

警告警告警告警告

データ TCMから命令をロードしようとすると、同一アドレスのオフチップメモリへのアクセスが発生する可能性があります。これはコアに依存します。詳細については、使用するプロセッサのテクニカルリファレンスマニュアルを参照して下さい。

Page 204: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

キャッシュと密結合メモリ

7-22 Copyright © 1999-2001 ARM Limited. All rights reserved. ARM DUI0056DJ-00

7.7.2 ARM966E-Sの初期化の初期化の初期化の初期化

コアの初期コンフィギュレーションは 2つの入力ピンによって制御されます。

VINITHI • HIGHのとき、ベクタテーブルが 0xFFFF0000に配置されます。

• LOWのとき、ベクタテーブルが 0x0に配置されます。

INITRAM • HIGHのとき、TCMがイネーブルされます。

• LOWのとき、TCMがディセーブルされます。

これらのピンは、起動時とリセット時のコアのコンフィギュレーションを決定します。これらのコンフィギュレーションはCP15への書き込みによってソフトウェアでオーバライドできます。

ここでは以下が可能です。

• INITRAMと VINITHIの両方を HIGHに固定する。

実行が 0xFFFF0000で開始されます。ブートコードが TCMを初期化し、ベクタテーブルを 0x0に再配置してパフォーマンスを向上させます。

• INITRAMを LOWで、VINITHIを HIGHで固定する。

実行が 0xFFFF0000で開始されます。ブートコードが TCMをイネーブルして初期化し、ベクタテーブルを 0x0に再配置してパフォーマンスを向上させます。

• INITRAMと VINITHIの両方を LOWに固定する。

実行がオフチップメモリ内の 0x0で開始されます。TCMをイネーブルして初期化する前に、ブートコードは最下位 128MB のアドレス範囲外に分岐する必要があります。

注意注意注意注意

VINITHIを LOWで固定する場合は、INITRAMを HIGHで固定しないで下さい。これに反すると予測不能な結果が生じます。

Page 205: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

キャッシュと密結合メモリ

ARM DUI0056DJ-00 Copyright © 1999-2001 ARM Limited. All rights reserved. 7-23

7.7.3 ARM966E-Sのウォームリセットのウォームリセットのウォームリセットのウォームリセット

TCMで実行するウォームリセットを実装できます。

INITRAMと VINITHIは、メモリマップレジスタで制御することができます。また、パワーオンリセットとウォームリセットには異なる動作を割り当てることが可能です。

例えば、パワーオンリセットでは両方のピンを LOWに設定することが考えられます。ブートコードはアプリケーションへの分岐前にウォームリセットの動作を再構成します。

TCMで実行するウォームリセットを実装できます。

ウォームリセットを実装するには以下を行うことができます。

• TCMを初期化する。

• INITRAMを HIGHに設定する。

• VINITHIを LOWに設定する。

7.7.4 ARM966E-Sのパフォーマンスのパフォーマンスのパフォーマンスのパフォーマンス

ARM966E-Sは以下の場合にピークパフォーマンスで動作します。

• TCMに保持されているコードを実行するとき

• TCMに保持されているデータにアクセスするとき

• ライトバッファがイネーブルされているとき

ARM9Eコアは以下の間停止します。

• データ TCMへの書き込み直後にデータ TCMからの読み出しが行われた場合、1サイクル

• 命令 TCMからのデータの読み出しが発生した場合、1サイクル

• 命令 TCMへのデータの書き込みが発生した場合、2サイクル

• 外部メモリがアクセスされたとき。この場合、停止サイクル数は以下に依存します。

— ライトバッファのドレイン

— 外部メモリシステム

Page 206: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

キャッシュと密結合メモリ

7-24 Copyright © 1999-2001 ARM Limited. All rights reserved. ARM DUI0056DJ-00

Page 207: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

ARM DUI0056DJ-00 Copyright © 1999-2001 ARM Limited. All rights reserved. 8-1

第 8章デバッグ通信チャネルデバッグ通信チャネルデバッグ通信チャネルデバッグ通信チャネル

本章ではデバッグ通信チャネル(DCC)の使用方法について説明します。本章は以下のセクションから構成されています。

• デバッグ通信チャネルについて:P. 8-2

• コマンドラインデバッギングコマンド:P. 8-3

• 通信チャネルビューのイネーブル:P. 8-4

• ターゲットのデータ転送:P. 8-5

• デバッグ通信のポーリング:P. 8-6

• 割り込み駆動型デバッグ通信:P. 8-12

• Thumb状態からのアクセス:P. 8-13

• セミホスティング:P. 8-14

Page 208: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

デバッグ通信チャネル

8-2 Copyright © 1999-2001 ARM Limited. All rights reserved. ARM DUI0056DJ-00

8.1 デバッグ通信チャネルについてデバッグ通信チャネルについてデバッグ通信チャネルについてデバッグ通信チャネルについて

ARM7TDMIや ARM9TDMIなどの ARMコアに組み込まれている EmbeddedICEロジックには、デバッグ通信チャネルが実装されています。このチャネルにより、JTAGポートとMulti-ICEなどのプロトコルコンバータを使用すれば、プログラムフローを停止させたりデバッグ状態に入らなくても、ターゲットとホストデバッガ間でデータの受け渡しを行うことができます。本章では、ターゲット上で実行しているプログラムとホストデバッガからのデバッグ通信チャネルへのアクセス方法を説明します。

ADSは、以下の方法によるデバッグ通信チャネルへのアクセスをサポートしています。

• armsdコマンドラインデバッガ

• AXDのチャネルビューワ機能

• Multi-ICEのセミホスティング

Page 209: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

デバッグ通信チャネル

ARM DUI0056DJ-00 Copyright © 1999-2001 ARM Limited. All rights reserved. 8-3

8.2 コマンドラインデバッギングコマンドコマンドラインデバッギングコマンドコマンドラインデバッギングコマンドコマンドラインデバッギングコマンド

armsdを使用してコマンドラインからデバッグ通信チャネルにアクセスするには、以下のコマンドを使用します。

ccin filename

ターゲットに読み出すデータを含むファイルを選択します。このコマンドにより、ホストからターゲットへの commsチャネル通信もイネーブルされます。

ccout filename

ターゲットからのデータを書き込むファイルを選択します。このコマンドにより、ターゲットからホストへの commsチャネル通信もイネーブルされます。

Page 210: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

デバッグ通信チャネル

8-4 Copyright © 1999-2001 ARM Limited. All rights reserved. ARM DUI0056DJ-00

8.3 通信チャネルビューのイネーブル通信チャネルビューのイネーブル通信チャネルビューのイネーブル通信チャネルビューのイネーブル

デバッグ通信チャネルビューは AXDでサポートされています。

8.3.1 AXDの通信チャネルビューの通信チャネルビューの通信チャネルビューの通信チャネルビュー

AXDでチャネルビューをイネーブルする方法については、AXD/armsdデバッガガイドの第 5章にある「[Control system view]ポップアップメニュー」の説明を参照して下さい。

AXDでチャネルビューを使用するには、AXD/armsdデバッガガイドの第 5章にある「[Comms Channel]プロセッサビュー」の説明を参照して下さい。

Page 211: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

デバッグ通信チャネル

ARM DUI0056DJ-00 Copyright © 1999-2001 ARM Limited. All rights reserved. 8-5

8.4 ターゲットのデータ転送ターゲットのデータ転送ターゲットのデータ転送ターゲットのデータ転送

デバッグ通信チャネルには、ARM命令 MCRおよび MRCを使用して、ARMコア上のコプロセッサ 14としてターゲットからアクセスします。

データ転送には以下の 2つのレジスタを使用します。

通信データ読み出しレジスタ通信データ読み出しレジスタ通信データ読み出しレジスタ通信データ読み出しレジスタ

デバッガからのデータの受信に使用される 32 ビット幅のレジスタです。以下の命令は、この読み出しレジスタの値を Rdに返します。

MRC p14, 0, Rd, c1, c0

通信データ書き込みレジスタ通信データ書き込みレジスタ通信データ書き込みレジスタ通信データ書き込みレジスタ

デバッガへのデータの送信に使用される 32ビット幅のレジスタです。以下の命令は、この書き込みレジスタに Rnの値を書き込みます。

MCR p14, 0, Rn, c1, c0

注意注意注意注意

ARM 10の DCCレジスタへのアクセス方法については、ARM10テクニカルリファレンスマニュアルを参照して下さい。ARM 9以降のプロセッサでは、使用する命令、ステータスビットの位置、ステータスビットの意味が異なります。

Page 212: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

デバッグ通信チャネル

8-6 Copyright © 1999-2001 ARM Limited. All rights reserved. ARM DUI0056DJ-00

8.5 デバッグ通信のポーリングデバッグ通信のポーリングデバッグ通信のポーリングデバッグ通信のポーリング

デバッグ通信チャネルには、通信データ読み出し /書き込みレジスタに加え、通信データ制御レジスタがあります。

以下の命令は、この制御レジスタの値を Rdに返します。

MRC p14, 0, Rd, c0, c0

この制御レジスタ内の 2ビットが、ターゲットとホストデバッガ間の同期ハンドシェークを決定します。

ビットビットビットビット 1((((Wビット)ビット)ビット)ビット)通信データ書き込みレジスタが(ターゲットの観点から)空いて

いるかどうかを示します。

W = 0 ターゲットアプリケーションによって新しいデータを

書き込むことができます。

W = 1 ホストデバッガが書き込みレジスタの新しいデータを

スキャンアウトします。

ビットビットビットビット 0((((Rビット)ビット)ビット)ビット)通信データ読み出しレジスタに(ターゲットの観点から)新しい

データがあるかどうかを示します。

R = 1 ターゲットアプリケーションによって新しいデータを

読み出すことができます。

R = 0 ホストデバッガが新しいデータを読み出しレジスタに

スキャンインすることができます。

注注注注

コプロセッサ 14はデバッガにとって意味をなさないため、デバッガがこれを使用してデバッグ通信チャネルに直接アクセスすることはできません。その代わり、デバッガはスキャンチェインを使用することによって、デバッグ通信チャネルレジスタとの間で読み出し /書き込みを行うことができます。デバッグ通信チャネルデータレジスタおよび制御レジスタは、EmbeddedICEロジック内のアドレスにマップされます(「EmbeddedICEロジックレジスタの表示」参照)。

EmbeddedICE ロジックレジスタの内容は、コプロセッサ 0 として armsd で表示させることができます。

8.5.1 EmbeddedICEロジックレジスタの表示ロジックレジスタの表示ロジックレジスタの表示ロジックレジスタの表示

AXDでは以下のように EmbeddedICEロジックレジスタを表示させることができます。

• GUIからの場合:[Processor Views]→ [Registers]をクリックし、EICE、EICE Watch 0、EICE Watch 1のいずれかを選択します。

• コマンドラインからの場合:reg EICEを入力します。

詳細については、MultiICEの説明書を参照して下さい。

Page 213: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

デバッグ通信チャネル

ARM DUI0056DJ-00 Copyright © 1999-2001 ARM Limited. All rights reserved. 8-7

8.5.2 ターゲットからデバッガへの通信ターゲットからデバッガへの通信ターゲットからデバッガへの通信ターゲットからデバッガへの通信

以下は、ARMコアで実行中のアプリケーションからホストで実行中のデバッガに通信するときのイベントシーケンスです。

1. ターゲットアプリケーションが、デバッグ通信チャネル書き込みレジスタが空いているかどうかをチェックします。これは MRC命令を使用してデバッグ通信チャネル制御レジスタを読み出し、Wビットがクリアされているかどうかでチェックされます。

2. W ビットがクリアされていればデバッグ通信書き込みレジスタがクリアされていることを示し、アプリケーションがコプロセッサ 14への MCR命令を使用して、このレジスタにワードを書き込みます。このレジスタへの書き込みによって、Wビットが自動的にセットされます。Wビットがセットされている場合は、デバッガがまだデバッグ通信書き込みレジスタを空にしていないことを示します。さらにワードを送信する必要がある場合、アプリケーションは W ビットがクリアされるまで、このビットをポーリングします。

3. デバッガはスキャンチェイン2を介してデバッグ通信制御レジスタをポーリングします。デバッガは W ビットがセットされていることを検出すると、デバッグ通信チャネルデータレジスタを読み出して、アプリケーションから送信されたメッセージを読み出すことができます。このデータ読み出しプロセスによって、デバッグ通信制御レジスタ内のWビットが自動的にクリアされます。

例 8-1は、上記のシーケンスを示しています。このサンプルコードはInstall_directory\Examples\dcc\outchan.sに収録されています。

例例例例 8-1

AREA OutChannel, CODE, READONLY ENTRY MOV r1,#3 ; Number of words to send ADR r2, outdata ; Address of data to sendpollout MRC p14,0,r0,c0,c0 ; Read control register TST r0, #2 BNE pollout ; if W set, register still fullwrite LDR r3,[r2],#4 ; Read word from outdata ; into r3 and update the pointer MCR p14,0,r3,c1,c0 ; Write word from r3 SUBS r1,r1,#1 ; Update counter BNE pollout ; Loop if more words to be written MOV r0, #0x18 ; Angel_SWIreason_ReportException LDR r1, =0x20026 ; ADP_Stopped_ApplicationExit SWI 0x123456 ; ARM semihosting SWIoutdata DCB "Hello there!" END

Page 214: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

デバッグ通信チャネル

8-8 Copyright © 1999-2001 ARM Limited. All rights reserved. ARM DUI0056DJ-00

このサンプルを実行するには:

1. outchan.sをアセンブルします。

armasm -g outchan.s

2. 出力オブジェクトをリンクさせます。

armlink outchan.o -o outchan.axf

このリックステップで、実行ファイル outchan.axfを作成します。

3. このイメージをロードし、通信チャネルの表示をイネーブルし、イメージを実行します。この手順は、使用するデバッガによって異なります。以下を参照して下さい。

• armsdの使用

• AXDの使用

armsdの使用の使用の使用の使用

armsdを使用する場合:

1. 以下のコマンドを使用してイメージを armsdにロードします。

armsd -li -adp -port s=1 outchan.axf

2. 通信をイネーブルして出力ファイルを開き、プログラムを実行します。

ccout outputgo

3. 実行が終了したら armsdを終了します。これでファイルを表示させ、転送が行われたことを確認できます。

AXDの使用の使用の使用の使用

AXDを使用する場合:

1. チャネルビューをイネーブルします。AXD/armsdデバッガガイドの第 5章にある「[Control system view]ポップアップメニュー」の説明を参照して下さい。

2. 上記で作成したイメージを AXDにロードします。

3. AXD のチャネルビューワを使用します。AXD/armsd デバッガガイドの第 5 章にある「[Comms Channel]プロセッサビュー」の説明を参照して下さい。

4. AXDのメイン画面で、[Execute]メニューから [Go]を選択し(または F5を押して)イメージを実行します。

これでターゲットから送信されたデータ(この例ではHello there!)が[ChannelViewer]ウィンドウに表示されます。

Page 215: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

デバッグ通信チャネル

ARM DUI0056DJ-00 Copyright © 1999-2001 ARM Limited. All rights reserved. 8-9

8.5.3 デバッガからターゲットへの通信デバッガからターゲットへの通信デバッガからターゲットへの通信デバッガからターゲットへの通信

以下は、ホストで実行しているデバッガからコアで実行しているアプリケーションにメッセージを転送する際のイベントシーケンスです。

1. デバッガがデバッガ通信制御レジスタの Rビットをポーリングします。Rビットがクリアされていれば、デバッグ通信読み出しレジスタがクリアされていることを示し、ターゲットアプリケーションが読み出すデータをこれに書き込むことができます。

2. デバッガはスキャンチェイン2を介してデバッグ通信読み出しレジスタにデータをスキャンインします。これによってデバッグ通信制御レジスタ内の Rビットが自動的にセットされます。

3. ターゲットアプリケーションがデバッグ通信制御レジスタ内のRビットをポーリングします。このビットがセットされていれば、アプリケーションがコプロセッサ 14からの読み出し命令である MRCを使用して読み出せるデータが、デバッグ通信読み出しレジスタ内に存在することを意味します。Rビットはこの読み出し命令の実行中にクリアされます。

以下はこれを示したターゲットアプリケーションコードの一部です。このサンプルは Install_directory\Examples\dcc\inchan.sに収録されています。

AREA InChannel, CODE, READONLY ENTRY MOV r1,#3 ; Number of words to read LDR r2, =indata ; Address to store data readpollin MRC p14,0,r0,c0,c0 ; Read control register TST r0, #1 BEQ pollin ; If R bit clear then loopread MRC p14,0,r3,c1,c0 ; read word into r3 STR r3,[r2],#4 ; Store to memory and ; update pointer SUBS r1,r1,#1 ; Update counter BNE pollin ; Loop if more words to read MOV r0, #0x18 ; Angel_SWIreason_ReportException LDR r1, =0x20026 ; ADP_Stopped_ApplicationExit SWI 0x123456 ; ARM semihosting SWI

AREA Storage, DATA, READWRITEindata DCB "Duffmessage#" END

4. ホストで、例として And goodbye!を含む入力ファイルを作成します。

5. 以下のコマンドを使用して、このコードのアセンブルとリンクを行います。

armasm -g inchan.sarmlink inchan.o -o inchan.axf

Page 216: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

デバッグ通信チャネル

8-10 Copyright © 1999-2001 ARM Limited. All rights reserved. ARM DUI0056DJ-00

これで inchan という名前のファイルに実行イメージを作成できます。次のステップ

は、選択するデバッガによって異なります。

以下を使用して、イメージのロード、通信チャネルビューのイネーブル、イメージの実行を行うことができます。

• armsd(コマンドライン操作の場合)

• AXD

コマンドの発行コマンドの発行コマンドの発行コマンドの発行

コマンドを発行する場合:

1. 以下のコマンドを使用して、イメージを armsdにロードします。

armsd -li -adp -port s=1 inchan.axf

メモリエリア indataを表示させると、このメモリエリアの初期ランダム内容を

見ることができます。

examine indata

2. 通信をイネーブルして入力ファイルを開き、プログラムを実行します。

ccin inputgo

3. 実行が終了してメモリを再表示させると、入力が examine indata で読み出されたことを確認できます。

examine indata

AXDの使用の使用の使用の使用

AXDを使用する場合:

1. チャネルビューをイネーブルします。AXD/armsdデバッガガイドの第 5章にある「[Control system view]ポップアップメニュー」の説明を参照して下さい。

2. 上記で作成したイメージを AXDにロードします。

3. AXD のチャネルビューワを使用します。AXD/armsd デバッガガイドの第 5 章にある「[Comms Channel]プロセッサビュー」の説明を参照して下さい。

4. チャネルビューワの [Send]フィールドに And goodbye!を入力し、[Send]ボタンをクリックします。[Left to Send]カウンタに、ターゲットに送信するためにストアされたバイト数が表示されます。

メモリエリア indataを表示させると、その初期内容を確認できます。

examine indata

Page 217: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

デバッグ通信チャネル

ARM DUI0056DJ-00 Copyright © 1999-2001 ARM Limited. All rights reserved. 8-11

5. AXDのメイン画面で、[Execute]メニューから [Go]を選択し(または F5を押して)、イメージを実行します。

6. 実行が完了してメモリを再表示させると、入力が以下で読み出されたことを確認できます。

examine indata

Page 218: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

デバッグ通信チャネル

8-12 Copyright © 1999-2001 ARM Limited. All rights reserved. ARM DUI0056DJ-00

8.6 割り込み駆動型デバッグ通信割り込み駆動型デバッグ通信割り込み駆動型デバッグ通信割り込み駆動型デバッグ通信

前出のサンプルは、DCCのポーリングを示しています。これらのサンプルは、COMMRXシグナルと COMMTXシグナルを EmbeddedICEロジックから割り込みコントローラに接続することにより、割り込み駆動型のサンプルに変換することができます。

これにより、サンプルで示した読み出しコードと書き込みコードを割り込みハンドラに移動させることができます。

割り込みハンドラの記述については、P. 5-23「割り込みハンドラ」を参照して下さい。

Page 219: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

デバッグ通信チャネル

ARM DUI0056DJ-00 Copyright © 1999-2001 ARM Limited. All rights reserved. 8-13

8.7 Thumb状態からのアクセス状態からのアクセス状態からのアクセス状態からのアクセス

Thumb命令セットにはコプロセッサ命令が含まれていないため、コアが Thumb状態にある間はデバッグ通信チャネルを使用することができません。

この問題の解決策としては以下の 3つの方法が考えられます。

• 各ポーリングルーチンを SWIハンドラ内に記述し、ARM状態または Thumb状態にあるときにこれを実行する。SWIハンドラに入るとコアがすぐに ARM状態に入るため、コプロセッサ命令を使用できるようになります。SWIの詳細については、第 5章「プロセッサ例外処理」を参照して下さい。

• Thumbコードで、ポーリングを実装する ARMサブルーチンへのインターワーキングコールを発生させる。ARMコードと Thumbコードの混合については、第 3章「ARMと Thumbのインターワーキング」を参照して下さい。

• ポーリング通信ではなく、割り込み駆動型通信を使用する。割り込みハンドラをARM命令で記述することにより、コプロセッサ命令に直接アクセスできます。

Page 220: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

デバッグ通信チャネル

8-14 Copyright © 1999-2001 ARM Limited. All rights reserved. ARM DUI0056DJ-00

8.8 セミホスティングセミホスティングセミホスティングセミホスティング

$semihosting_enabled=2 を指定して Multi-ICE を使用することにより、デバッグ通信チャネルをセミホスティングに使用することができます。詳細については、Multi-ICEユーザガイドを参照して下さい。

Page 221: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

ARM DUI0056DJ-00 Copyright © 1999-2001 ARM Limited. All rights reserved. Glossary-1

用語集用語集用語集用語集

ADS ARMデベロッパスイート参照。

ANSI 米国規格協会(American National Standards Institute)。他の中でも特にコンピュータソフトウェアの規格を規定する団体です。

Angel ARMベースのハードウェアで実行するアプリケーションの開発とデバッグを可能にするデバッグモニタ。Angelは、ARM状態または Thumb状態で動作するアプリケーションをデバッグすることができます。

ARMデベロッパデベロッパデベロッパデベロッパ

スイートスイートスイートスイート

支援文書およびサンプルを含み、ARMファミリの RISC プロセッサ用アプリケーションを記述してデバッグするためのアプリケーションスイート。

ARM拡張デバッガ拡張デバッガ拡張デバッガ拡張デバッガ デバッグエージェントを利用してデバッグターゲット上で動作するソフトウェアの実行を検査・制御するための、ARM の最新デバッガソフトウェア。AXD には Windows版と UNIX版の 2つのバージョンがあります。

ARMulator 命令セットシミュレータ。各種 ARM プロセッサの命令セットとアーキテクチャをシ

ミュレートするモジュールの集合です。

armsd ARMシンボリックデバッガ(armsd)は、C言語などのハイレベルデバッギングサポート、アセンブリ言語のローレベルサポートを提供するインタラクティブなソースレベルデバッガです。armsdは、サポートされている全てのプラットフォーム上で動作するコマンドラインデバッガです。

Page 222: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

用語集

Glossary-2 Copyright © 1999-2001 ARM Limited. All rights reserved. ARM DUI0056DJ-00

ATPCS ARM/Thumbプロシージャコール標準。サブルーチンコールに関するレジスタとスタックの使用方法を定義します。

AXD ARM拡張デバッガ参照。

ビッグエンディアンビッグエンディアンビッグエンディアンビッグエンディアン ワードの最下位バイトが最上位バイトよりも上位アドレスに位置するメモリ構成。

標準構造フレーム標準構造フレーム標準構造フレーム標準構造フレームアドレスアドレスアドレスアドレス

DWARF 2におけるスタック上のアドレスであり、割り込まれた関数の呼び出しフレームがどこにあるかを指定します。

CFA 標準構造フレームアドレス参照。

コプロセッサコプロセッサコプロセッサコプロセッサ 特定の操作に使用される補助プロセッサ。一般的には、浮動小数点数値計算、シグナル処理、メモリ管理などに使用されます。

ダブルワードダブルワードダブルワードダブルワード 64 ビット単位の情報。ダブルワードの内容は、指定されていない限り符号なし整数とみなされます。

DWARF Debug With Arbitrary Record Format(任意レコード形式でのデバッグ)の略。

EC++ 組み込みアプリケーション用に作られた C++のバリアント。

ELF 実行リンク形式。

実行ビュー実行ビュー実行ビュー実行ビュー イメージがメモリにロードされて実行を開始した後の、領域およびセクションのアドレス。

フラッシュメモリフラッシュメモリフラッシュメモリフラッシュメモリ アプリケーションコードの保持に頻繁に使用される不揮発性メモリ。

ハーフワードハーフワードハーフワードハーフワード 16 ビット単位の情報。ハーフワードの内容は、指定されていない限り符号なし整数とみなされます。

ヒープヒープヒープヒープ コンピュータメモリ内で、新しい変数の作成に使用可能な部分。

ICE インサーキットエミュレータ。

IDE 統合開発環境(Code Warrior)。

イメージイメージイメージイメージ 実行を目的にプロセッサにロードされた実行可能ファイル。

プロセッサにロードされ、実行スレッドを与えられたバイナリ実行ファイル。1つのイメージが複数のスレッドをもつ場合もあります。イメージは、デフォルトのスレッドが実行されるプロセッサに関連付けられます。

インラインインラインインラインインライン 汎用サブルーチンを保持せずに、使用されるたびにコード内で繰り返される関数。Cまたは C++プログラム内に配置されるアセンブラコードのこと。

出力セクション参照。

Page 223: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

用語集

ARM DUI0056DJ-00 Copyright © 1999-2001 ARM Limited. All rights reserved. Glossary-3

入力セクション入力セクション入力セクション入力セクション コードまたは初期化データを保持する、あるいはアプリケーションの起動前にゼロに設定する必要があるメモリフラグメントを記述するセクション。

出力セクション参照。

インターワーキングインターワーキングインターワーキングインターワーキング ARMコードと Thumbコードの両方を使用するアプリケーションの生成。

ライブラリライブラリライブラリライブラリ アセンブラまたはコンパイラの出力オブジェクトの集合をグループ化した 1 つのリポジトリ。

リンカリンカリンカリンカ 1つ以上のソースアセンブラ /コンパイラ出力オブジェクトから 1つのイメージを生成するソフトウェア。

リトルエンディアンリトルエンディアンリトルエンディアンリトルエンディアン ワードの最下位バイトが最上位バイトよりも下位アドレスに位置するメモリ構成。ビッグエンディアン参照。

ローカルローカルローカルローカル 作成元のサブルーチンだけがアクセス可能なオブジェクト。

ロードビューロードビューロードビューロードビュー イメージがメモリにロードされ、実行がまだ開始されていないときの領域およびセクションのアドレス。

メモリ管理ユニットメモリ管理ユニットメモリ管理ユニットメモリ管理ユニット キャッシュおよびメモリブロックへのアクセス許可を制御するほか、仮想アドレスを物理アドレスに変換するハードウェア。

MMU メモリ管理ユニット参照。

Multi-ICE マルチプロセッサデバッグエージェント。ARMの登録商標です。

出力セクション出力セクション出力セクション出力セクション RO、RW、ZI のうちで同じ属性を持った、連続する一連の入力セクションから構成されるセクション。出力セクションは、領域と呼ばれるさらに大きなフラグメントにグループ化されます。これらの領域がグループ化されて最終的な実行イメージが生成されます。

領域参照。

PCS プロシージャコール標準。

ATPCS参照。

PIC 位置独立コード。

ROPI参照。

PID 位置独立データまたは ARMプラットフォーム独立開発(PID)ボード。

RWPI参照。

プロファイリングプロファイリングプロファイリングプロファイリング パフォーマンスの測定や重要コードエリアの特定を目的に、デバッグ対象プログラムの実行中の統計データを蓄積したもの。

プログラムイメージプログラムイメージプログラムイメージプログラムイメージ イメージ参照。

Page 224: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

用語集

Glossary-4 Copyright © 1999-2001 ARM Limited. All rights reserved. ARM DUI0056DJ-00

リエントランシリエントランシリエントランシリエントランシ サブルーチンコードの 1インスタンス以上をアクディブにするサブルーチンの機能。サブルーチンコールの各インスタンスは、必要とするスタティックデータの独自のコピーを保持します。

再マッピング再マッピング再マッピング再マッピング 物理メモリまたはデバイスのアドレスを、アプリケーションの実行開始後に変更すること。通常、この動作は初期化完了後に ROMを RAMに置き換えるために行われます。

領域領域領域領域 イメージ内において、1~ 3個の連続する一連の出力セクション(RO、RW、ZI)から構成される領域。

再対象化再対象化再対象化再対象化 ある実行環境に合わせて設計されたコードを別の実行環境に移動するプロセス。

ROPI 読み出し専用位置独立。コードおよび読み出し専用データのアドレスはランタイムに変更することが可能です。

RTOS リアルタイムオペレーティングシステム。

RWPI 読み出し /書き込み位置独立。読み出し /書き込みデータのアドレスはランタイムに変更することが可能です。

分散ローディング分散ローディング分散ローディング分散ローディング 1つの大きなブロックを使用するのではなく、コードセクションとデータセクションのアドレスを個々に割り当て、これらをグループ化すること。

セクションセクションセクションセクション イメージを構成するソフトウェアコードまたはデータのブロック。

入力セクション参照。

セミホスティングセミホスティングセミホスティングセミホスティング ターゲットがアプリケーションコード内で発生した I/O要求を、その I/O自体をサポートしようとするのではなく、ホストシステムに通知するメカニズム。

SWI ソフトウェア割り込み。プロセッサにプログラマが指定したサブルーチンを呼び出させる命令。ARMによってセミホスティングを処理するために使用されます。

ターゲットターゲットターゲットターゲット アプリケーションを実行する実ターゲットプロセッサ(実際の、またはシミュレートされたプロセッサ)。

スレッドスレッドスレッドスレッド プロセッサ上の実行コンテキスト。スレッドは常にプロセッサに関連付けられますが、必ずしもイメージに関連付けられるとは限りません。

ベニアベニアベニアベニア プロセッサ状態の変更要件、あるいは現在のプロセッサ状態では到達不可能なアドレスへの分岐要件があるときに、サブルーチンコールに使用される小さなコードブロック。

ワードワードワードワード 32 ビット単位の情報。ワードの内容は、指定されていない限り符号なし整数とみなされます。

Page 225: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

ARM DUI0056DJ-00 Copyright © 1999-2001 ARM Limited. All rights reserved. Index-1

Index

The items in this index are listed in alphabetical order, with symbols and numerics appearing at the end. The references given are to page numbers.

AAccessing

debug comms channel 1-8, 8-2ANSI C 4-20

header files 4-20ARM architecture v5T

interworking ARM and Thumb 3-10

Assemblerinline, armasm differences 4-7inline, see Inline assemblersmode changing 3-8

Assembly languagecalling from C 4-20inline, armasm differences 4-7interrupt handlers 5-28interworking ARM and Thumb 3-6,

3-15interworking using veneers 3-15

ATPCS 2-1conformance criteria 2-3floating-point options 2-17

interworking ARM and Thumb 2-16, 3-2, 7-2

leaf routine 2-12local variables 2-4memory state 2-3parameter passing 2-4, 2-9process 2-3processes 2-15read-only position independence

2-14read-write position independence

2-15reentrant routines 2-15register names 2-5register roles 2-4ROPI 2-14RWPI 2-15stack limit checking 2-11stack terminology 2-6static base register 2-15swstna 2-11threads 2-3, 2-15variadic routines 2-10

variants 2-2ATPCS options

/interwork 3-4

BBanked registers 5-3Base classes

in mixed languages 4-19Bit 0, use in BX instruction 3-7BL instruction 4-6BX instruction 3-7, 4-7

bit 0 usage 3-7

CC

callingfrom assembler 4-18from C++ 4-18

calling assembler 4-20

Page 226: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

Index

Index-2 Copyright © 1999-2001 ARM Limited. All rights reserved. ARM DUI0056DJ-00

global variables from assembly language 4-15

Interworking ARM and Thumb 3-11

linkage 4-18using header files from C++ 4-16

Callingassembler from C++ 4-18C from assembly language 4-18C from C++ 4-18, 4-20C++ from assembly language 4-18interworking examplesinterworking veneerslanguage conventions 4-18

Chaining exception handlers 5-38Code

density and interworking 3-3, 7-3Code size

measuring 6-47Command-line operation

of debug comms channel 8-3Comments

inline assemblers 4-3Comms channel, debug 8-1Comms data registers 8-5Constants, inline assemblers 4-5Context switch 5-31Coprocessor 14 8-5Coprocessors

Undefined Instruction handlers 5-34

CPSR 5-5C++

asm 4-2calling

from assembler 4-18from C 4-18

calling conventions 4-19data types in mixed languages 4-19string literal 4-2

DData Abort

exception 5-2handler 5-36, 5-42LDM 5-36LDR 5-36

returning from 5-8STM 5-36STR 5-36SWP 5-36

Data size, measuring 6-47Data types 4-19Debug

comms channel viewing 8-4communications channel 8-1interrupt-driven comms 8-12polled communications 8-6

Debuggerscommunicating with target 8-9

Directives, assemblerENTRY 6-8

Directives, assembly languageIMPORT 4-15

EEnabling DCC viewing 8-4Exception handlers

chaining 5-38Data Abort 5-36, 5-42extending 5-38FIQ 5-42installing 5-9installing from C 5-11installing on reset 5-9interrupt 5-23IRQ 5-42nested 5-24Prefetch Abort 5-35, 5-42reentrant 5-24Reset 5-33returning from 5-6subroutines in 5-45SWI 5-14, 5-15, 5-18, 5-42Thumb 5-40Undefined Instruction 5-34, 5-42

Exceptions 5-2Data Abort 5-8entering 5-5FIQ 5-7initialization code for ROM images

6-8installing handlers 5-9IRQ 5-2, 5-7

leaving 5-5Prefetch Abort 5-2, 5-8priorities 5-3reset 5-2response by processors 5-5returning from 5-7, 5-42SWI 5-2, 5-7SWI handlers 5-14, 5-15, 5-18Undefined Instruction 5-2, 5-7use of modes 5-3use of registers 5-3vector table 5-3, 5-9

Executionspeed 3-3, 5-23

Extending exception handlers 5-38extern "C" 4-16, 4-18, 4-20

FFault address register 5-37FIQ 5-2, 5-23

handler 5-7, 5-23, 5-42registers 5-23

Floating-pointATPCS options 2-17FPA 2-20VFP 2-18

FPAUndefined Instruction handlers

5-34FPA architecture 2-20

IIEEE 754 2-19Illegal address 5-2implicit this 4-18IMPORT directive 4-15Inline assemblers 4-2

accessing structures 4-15ADR pseudo-instruction 4-7ADRL pseudo-instruction 4-7ALU flags 4-5, 4-7, 4-9BL instruction 4-6branches 4-3BX instruction 4-7C global variables 4-15

Page 227: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

Index

ARM DUI0056DJ-00 Copyright © 1999-2001 ARM Limited. All rights reserved. Index-3

C variables 4-4, 4-9commas 4-9comments 4-3complex expressions 4-4constants 4-5corrupted registers 4-3CPSR 4-5C, C++ expressions 4-4, 4-5, 4-7DC directives 4-6examples 4-11floating point instructions 4-8instruction expansion 4-5interrupts 4-11invoking 4-2labels 4-3LDM instruction 4-7long multiply 4-13MUL instruction 4-5multiple lines 4-3operand expressions 4-4physical registers 4-5, 4-7register corruption 4-6, 4-9saving registers 4-10sign extension 4-4stacking registers 4-10STM instruction 4-7storage declaration 4-6subroutine parameters 4-6SWI instruction 4-6writing to pc 4-2, 4-5# 4-5

Instruction expansion 4-5Instructions, assembly language

BL 4-6BX 3-7SWI 4-6, 5-14SWI (Thumb) 5-43

Interrupt handlers 5-23Interrupt-driven debug comms 8-12Interrupts

prioritization 5-30Interworking ARM and Thumb 3-1,

7-1ARM architecture v5T 3-10assembly language 3-6, 3-15ATPCS 3-2, 3-18, 7-2BX instruction 3-7C 3-12C and C++ 3-11

C and C++ libraries 3-14compiler command-line options

3-14compiling code 3-11CPSR 3-9detecting calls 3-5duplicate functions 3-14examples 3-9, 3-12, 3-16exceptions 3-3leaf functions 3-11mixed languages 3-15, 3-17, 7-2,

7-12non-Thumb processors 3-12procedure call standards 3-2, 7-2rules 3-14veneers 3-11, 3-15

IRQ 5-23handler 5-7, 5-42

IRQ exception 5-2I/O devices, ROM applications 6-9

JJTAG 1-8, 8-2Jump table 5-15, 5-43

LLabels, inline assemblers 4-6Leaf functions 3-11Leaf routine 2-12Link register 5-3Linking

and interworking 3-5, 3-11the C library 6-44

MMangling symbol names 4-18, 4-20Memory management unit 6-8Memory map

layout 6-4organization of 6-4RAM at address 0 6-4ROM at address 0 6-4

Mixed endian 2-20

Mixed language programminginterworking ARM and Thumb

3-15, 3-17, 7-2, 7-12

NNested interrupts 5-24Nested SWIs 5-18

OOperand expressions, inline assemblers

4-4

PPIC 2-14PID 2-15Pointers

data members 4-20member functions 4-20

Polled debug communications 8-6Power-up 1-6, 5-2Prefetch Abort 5-2

handler 5-35, 5-42returning from 5-8

Process control blocks 5-31Processors

responding to exceptions 5-5Protocol converter 1-8, 8-2Pure endian 2-19

RRAM

at address 0 6-4measuring requirements 6-48

Reentrant routines 2-15References 4-19Registers

debug comms channel 8-5REMAP 6-5

REMAP register 6-5Reset exception 5-2Reset exception handler 5-33

Page 228: ARM デベロッパスイートinfocenter.arm.com/help/topic/com.arm.doc.dui0056dj/DUI... · 3.3 c と c++ のインターワーキングおよびベニア..... 3-11 3.4 ベニアを使用した

Index

Index-4 Copyright © 1999-2001 ARM Limited. All rights reserved. ARM DUI0056DJ-00

RESET vector 6-5Return address 5-7Return instruction 5-7ROM

at address 0 6-4measuring requirements 6-48

ROPI 2-14RWPI 2-15

SScalar mode 2-18Scatter load description file

examples 6-14, 6-25Scatter loading

writing code for ROM 6-14, 6-25Semihosting mode 8-14Soft reset 1-6, 5-2Software FPA emulator

Undefined Instruction handlers 5-34

Software interrupt, see SWIsSPSR 5-3, 5-5

T bit 5-43Stack terminology 2-6Stacks 5-3

initialization code for ROM images 6-9

stack pointer 5-3supervisor 5-16

Static base 2-15Storage declaration, inline assemblers

4-6String copying

assembler 4-20Supervisor mode 5-18Supervisor stack 5-16SWI exception 5-2SWI instruction 4-6, 5-14

Thumb 5-43SWIs

handlers 5-14, 5-15, 5-18, 5-42indirect 5-22returning from 5-7Thumb state 5-43

swstna 2-11Symbol names, mangling 4-18, 4-20System decoder 6-6

System mode 5-45

TTarget

communicating with debugger 8-7this, implicit 4-18Threads 2-15Thumb

access to DCC 8-13and __irq 5-24BX instruction 3-7changing to Thumb state, example

3-8code for ROM applications 6-10exception handler 5-40handling exceptions 5-40inline assemblers 4-2interworking with ARM 3-3, 7-3return address 5-42using duplicate function names

3-14

UUndefined Instruction exception 5-2Undefined Instruction handler 5-7,

5-34, 5-42User mode 5-3

VVariadic routines 2-10Vector mode 2-18Vector table 5-3, 5-9, 5-23, 5-40Vector table and caches 5-13Vectors

exception 6-8RESET 6-5

Veneers, see InterworkingVFP architecture 2-18

WWriting code for ROM

common problems 6-44critical I/O devices 6-9entry point 6-8exception vectors 6-8initialization 6-7memory for C code 6-10MMU 6-8processor mode 6-9processor state 6-10RAM at address 0 6-4ROM at address 0 6-4, 6-11ROM at its base address 6-11scatter loading 6-14, 6-25stack pointers 6-9undefined __main 6-44vector code eliminated 6-45

Numerics0-init data 6-48

Symbols$top_of_memory 6-9__semihosting_swi_guard 6-44__user_initial_stackheap() 6-9__use_no_semihosting_swi pragma

6-34, 6-44