link 未来から過去へ表示(*)
link 過去から未来へ表示

link もっと前
   2021年 9月 26日 ---> 2021年 9月 17日
link もっと後

2021年 9月 20日

RISC-V の cmodel

目次: RISC-V - まとめリンク

RISC-V には code model という概念があり、ざっくり言うとメモリアクセスやジャンプの際に参照するアドレスの作り方を指定します。medlow と medany の 2つがあり medlow がデフォルトです。

詳しくは GCC のマニュアル RISC-V Options (Using the GNU Compiler Collection (GCC)) や SiFive のエンジニアによる解説 All Aboard, Part 4: The RISC-V Code Models - SiFive を読んでいただくのが良いかと思いますが、ここではどんなときにエラーになるかに重点を置いて、いくつか例を挙げたいと思います。

medlow

モデル medlow は 32bit 絶対値でアドレスを指定します。具体的には lui 命令とロード命令などの 12ビットオフセットを使います。lui 命令とは 20ビットの immediate を 12ビット左シフトして、符号拡張する命令のことです。

medlow 指定時に生成されるコードの例
lui a1, 0x12345    # 12ビットシフトされた値 0x12345000 が a1 に格納される
ld a0, 0x678(a1)   # アドレス a1 + 0x678 = 0x12345000 + 0x678 から a0 に値をロードする

このようなコードが生成されます。絶対値は -2GB 〜 +2GB までしか生成できませんので、全てのシンボルが範囲に収まっている必要があります。32bit アドレスを使っている場合は全てのアドレス範囲をカバーできますが、64bit アドレスを使っている場合は 0x00000000_00000000〜0x00000000_7fffffff または 0xffffffff_80000000〜0xffffffff_ffffffff のアドレス範囲にシンボルを配置しなければなりません。範囲外にシンボルを配置しようとすると、

medlow のアドレス生成範囲外となるケース

// a.c

extern volatile int *hoge;

void _start(void)
{
	*hoge = 1;
}


/* a.ld */

OUTPUT_ARCH("riscv")
ENTRY(_start)

SECTIONS
{
	PROVIDE(hoge = 0x100000000);    /* 0x1_00000000 は medlow の範囲外 */
}
medlow のアドレス生成範囲外となるケース(リンク結果)
$ riscv64-zephyr-elf-gcc -march=rv64gc -Wall -g -mabi=lp64d -mcmodel=medlow -nostdlib -T a.ld a.c --save-temp

a.o: in function `_start':
test-medany/a.c:5:(.text+0x6): relocation truncated to fit: R_RISCV_HI20 against symbol `hoge' defined in *ABS* section in a.out
collect2: error: ld returned 1 exit status

リンカーがエラーを出します。hoge のアドレスを変更し -2GB 〜 +2GB の範囲(0xffffffff_80000000 や 0x00000000_70000000 など)にするとリンクが通ります。

medany

もう 1つの medany は、PC 相対でアドレス指定します。具体的にはアドレスの場合は auipc 命令と addi 命令、ジャンプの場合は auipc 命令と jalr 命令の 12ビットオフセットを使います。auipc 命令とは、20ビットの immediate を 12ビット左シフトして、符号拡張したあと PC に加算する命令のことです。

PC が 0x1_40000000 付近で hoge が 0x1_a89abcd0 だとすると、

medany 指定時に生成されるコードの例
アドレスの場合

140000006: auipc   a5,0x689ac    # 12ビットシフトされた値 0x689ac000 + PC 0x1_40000006 = 0x1_a89ac006 が a5 に格納される
14000000a: addi    a5,a5,-822    # 0x1_a89ac006 - 822 = 0x1_a89abcd0 = hoge のアドレスが a5 に格納される


ジャンプの場合

140000008: auipc   ra,0x689ac    # 12ビットシフトされた値 0x689ac000 + PC 0x1_40000008 = 0x1_a89ac008 が ra に格納される
14000000c: jalr    -824(ra)      # ra 0x1_a89ac006 - 824 = 0x1_a89abcd0 = hoge のアドレスにジャンプする

このようなコードが生成されます。相対アドレスは PC の現在地 -2GB 〜 +2GB までしか生成できません。medlow モデルより対応できる範囲は広がったものの、いかなるアドレスでも対応できるわけではないです。例えばコード領域とデータ領域をあまりにも遠くすると、

medany のアドレス生成範囲外となるケース

// a.c

extern volatile int *hoge;

void _start(void)
{
	*hoge = 1;
}


/* a.ld */

OUTPUT_ARCH("riscv")
ENTRY(_start)

MEMORY
{
	TEXT(rx)  : ORIGIN = 0x0000000140000000, LENGTH = 0x10000
}

SECTIONS
{
	/* hoge をコード領域から 2GB 以上離して配置する */
	PROVIDE(hoge = 0x1c89abcd0);

	/* コード領域を 0x1_40000000 にする */
	.text : {
		*(.text*);
	} > TEXT
}
medany のアドレス生成範囲外となるケース(リンクの結果)
$ riscv64-zephyr-elf-gcc -march=rv64gc -Wall -g -mabi=lp64d -mcmodel=medany -nostdlib -T a.ld a.c --save-temp

a.o: in function `_start':
test-medany/a.c:5:(.text+0x6): relocation truncated to fit: R_RISCV_PCREL_HI20 against symbol `hoge' defined in *ABS* section in a.out
collect2: error: ld returned 1 exit status

シンボル hoge が位置するアドレスは絶対値 -2GB 〜 +2GB の範囲外であり、コード領域からも離れているため PC 相対 -2GB 〜 +2GB の範囲外でもあります。よって medlow モデルでも medany モデルでもリンクエラーとなります。

編集者: すずき(更新: 2021年 9月 21日 23:04)

コメント一覧

  • コメントはありません。
open/close この記事にコメントする



link もっと前
   2021年 9月 26日 ---> 2021年 9月 17日
link もっと後

管理用メニュー

link 記事を新規作成

合計:  counter total
本日:  counter today

link About www.katsuster.net
RDF ファイル RSS 1.0
QR コード QR コード

最終更新: 9/24 14:00

カレンダー

<2021>
<<<09>>>
---1234
567891011
12131415161718
19202122232425
2627282930--

最近のコメント 5件

  • link 21年03月03日
    すずき 「お役に立てたようで幸いです。」
    (更新:06/17 17:24)
  • link 21年03月03日
    Shige 「とても参考になりました。\nGood!!...」
    (更新:06/17 13:28)
  • link 20年12月19日
    すずき 「なるほど、地元愛 No.1 は福岡なんで...」
    (更新:05/02 00:08)
  • link 20年12月19日
    Twitterから 「> 大学時代に知り合った人たちを思...」
    (更新:04/28 13:38)
  • link 21年04月12日
    すずき 「コメントありがとうございます。ご参考にな...」
    (更新:04/18 22:39)

最近の記事 3件

link もっとみる
  • link 21年04月05日
    すずき 「[GCC を調べる - GCC 8.3 の folding バ] ...」
    (更新:09/24 14:00)
  • link 21年09月20日
    すずき 「[RISC-V の cmodel] 目次: RISC-V - まと...」
    (更新:09/21 23:04)
  • link 21年06月18日
    すずき 「[RISC-V まとめリンク] 目次: RISC-V - まとめリ...」
    (更新:09/21 23:01)

こんてんつ

open/close wiki
open/close Java API

過去の日記

open/close 2002年
open/close 2003年
open/close 2004年
open/close 2005年
open/close 2006年
open/close 2007年
open/close 2008年
open/close 2009年
open/close 2010年
open/close 2011年
open/close 2012年
open/close 2013年
open/close 2014年
open/close 2015年
open/close 2016年
open/close 2017年
open/close 2018年
open/close 2019年
open/close 2020年
open/close 2021年
open/close 過去日記について

その他の情報

open/close アクセス統計
open/close サーバ一覧
open/close サイトの情報