<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-3477330834625238216</id><updated>2011-04-22T03:47:12.607+09:00</updated><title type='text'>QEMU memo</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://qemumemo.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3477330834625238216/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://qemumemo.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>aloha</name><uri>http://www.blogger.com/profile/17250121836567925230</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>22</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-3477330834625238216.post-2358459275807623724</id><published>2009-04-07T12:59:00.002+09:00</published><updated>2009-04-07T13:12:36.467+09:00</updated><title type='text'>kernel 2.6.29 と差し替えてみる</title><content type='html'>QEMU のサイトからダウンロードできる arm-test 0.2 の kernel を差し替えてみる。&lt;br /&gt;&lt;br /&gt;http://www.nongnu.org/qemu/arm-test-0.2.tar.gz&lt;br /&gt;&lt;br /&gt;kernel.org から最新の 2.6.29 を取ってくる。&lt;br /&gt;&lt;br /&gt;http://www.kernel.org/pub/linux/kernel/v2.6/linux-2.6.29.tar.bz2&lt;br /&gt;&lt;br /&gt;クロスコンパイラは、結局 CodeSourcery から持ってきた。&lt;br /&gt;&lt;br /&gt;http://www.codesourcery.com/sgpp/lite/arm/portal/subscription?@template=lite&lt;br /&gt;&lt;br /&gt;VMWare 上に最低限の Debian 5.0.0 環境を作ってインストール (単に tarball を展開するだけでも OK)。&lt;br /&gt;.bashrc に&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;export LANG=C&lt;br /&gt;export ARCH=arm&lt;br /&gt;export CROSS_COMPILE=arm-none-linux-gnueabi-&lt;br /&gt;export PATH=&lt;span style="font-style:italic;"&gt;/path/to/&lt;/span&gt;CodeSourcery/Sourcery_G++_Lite/bin:$PATH&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;ARCH が大文字じゃないと駄目なので注意（参考サイト [1] では小文字になっててはまった…）。&lt;br /&gt;&lt;br /&gt;参考サイト&lt;br /&gt;&lt;br /&gt;[1] http://fedoraproject.org/wiki/Architectures/ARM/HowToQemu&lt;br /&gt;[2] http://d.hatena.ne.jp/himainu/20080430&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;$ cp arch/arm/configs/versatile_defconfig .config&lt;br /&gt;$ make menuconfig&lt;br /&gt;&lt;br /&gt;Enable DHCP Support (CONFIG_IP_PNP_DHCP). &lt;br /&gt;&lt;br /&gt;Networking -&gt; Networking Support -&gt; Networking Options -&gt; TCP/IP Networking -&gt;&lt;br /&gt;&lt;br /&gt;Enable Universal Tun/Tap Driver Support (CONFIG_TUN)&lt;br /&gt;&lt;br /&gt;Device Drivers -&gt; Network Device Support -&gt;&lt;br /&gt;&lt;br /&gt;Enable ARM EABI Support (CONFIG_AEABI)&lt;br /&gt;&lt;br /&gt;Kernel Features -&gt;&lt;br /&gt;&lt;br /&gt;Enable tmpfs support (CONFIG_TMPFS)&lt;br /&gt;File Systems -&gt; Pseudo File Systems -&gt;&lt;br /&gt;&lt;br /&gt;Enable PCI (CONFIG_PCI)&lt;br /&gt;&lt;br /&gt;SCSI LOW level drivers -&gt; CONFIG_SCSI_SYM53C8XX_2&lt;br /&gt;&lt;br /&gt;$ make&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;できた arch/arm/boot/zImage を持ってきて、arm-test 以下に置いたと仮定して。&lt;br /&gt;&lt;br /&gt;$ qemu-0.9.1/arm-softmmu/qemu-system-arm.exe -M versatilepb -kernel arm-test/zImage -initrd arm-test/arm_root.img&lt;br /&gt;&lt;br /&gt;で起動した。ちょっとフォントが変だけど…&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3477330834625238216-2358459275807623724?l=qemumemo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://qemumemo.blogspot.com/feeds/2358459275807623724/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://qemumemo.blogspot.com/2009/04/kernel-2629.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3477330834625238216/posts/default/2358459275807623724'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3477330834625238216/posts/default/2358459275807623724'/><link rel='alternate' type='text/html' href='http://qemumemo.blogspot.com/2009/04/kernel-2629.html' title='kernel 2.6.29 と差し替えてみる'/><author><name>aloha</name><uri>http://www.blogger.com/profile/17250121836567925230</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3477330834625238216.post-8845098248108964776</id><published>2009-04-03T10:49:00.004+09:00</published><updated>2009-04-03T10:59:31.089+09:00</updated><title type='text'>machine number</title><content type='html'>Linux Kernel は、ブートローダの中でマシンチェックを行っているので、r1 レジスタに適切な machine number を入れておかないとブートできない。&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.arm.linux.org.uk/developer/machines/"&gt;http://www.arm.linux.org.uk/developer/machines/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;を見ると ARM Versatile Porting Board (versatile_pb) は 387 と書いてある。&lt;br /&gt;&lt;br /&gt;QEMU の hw/versatilepb.c を見ると、vab_init() の中で versatile_init() の最後の引数に 0x183 を指定して呼び出している。まさしく 0x183 = 387。&lt;br /&gt;&lt;br /&gt;というわけで、マジックナンバーの謎が解けた。linux kernel のロードのための引数だったのね。static &lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;br /&gt;void vpb_init(int ram_size, int vga_ram_size,&lt;br /&gt;                     const char *boot_device, DisplayState *ds,&lt;br /&gt;                     const char *kernel_filename, const char *kernel_cmdline,&lt;br /&gt;                     const char *initrd_filename, const char *cpu_model)&lt;br /&gt;{&lt;br /&gt;    versatile_init(ram_size, vga_ram_size,&lt;br /&gt;                   boot_device, ds,&lt;br /&gt;                   kernel_filename, kernel_cmdline,&lt;br /&gt;                   initrd_filename, cpu_model, 0x183);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;...&lt;br /&gt;&lt;br /&gt;QEMUMachine versatilepb_machine = {&lt;br /&gt;    "versatilepb",&lt;br /&gt;    "ARM Versatile/PB (ARM926EJ-S)",&lt;br /&gt;    vpb_init,&lt;br /&gt;};&lt;br /&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3477330834625238216-8845098248108964776?l=qemumemo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://qemumemo.blogspot.com/feeds/8845098248108964776/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://qemumemo.blogspot.com/2009/04/machine-number.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3477330834625238216/posts/default/8845098248108964776'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3477330834625238216/posts/default/8845098248108964776'/><link rel='alternate' type='text/html' href='http://qemumemo.blogspot.com/2009/04/machine-number.html' title='machine number'/><author><name>aloha</name><uri>http://www.blogger.com/profile/17250121836567925230</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3477330834625238216.post-7147029327344114049</id><published>2009-02-07T18:54:00.002+09:00</published><updated>2009-02-07T18:58:04.248+09:00</updated><title type='text'>QEMU stdvga</title><content type='html'>&lt;a href="http://hrb.osask.jp/wiki/?advance/QEMUVGA"&gt;http://hrb.osask.jp/wiki/?advance/QEMUVGA&lt;/a&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;vl.c の中でオプション解析。デフォルトは cirrus_vga_enable になってるみたい。&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;pci/isa_vga_init() で作ったビデオカードが stdvga 相当になるみたい。&lt;/div&gt;&lt;div&gt;（他はそれぞれ、vga の代わりに cirrus  や vmsvga が付いた初期化関数を使う）&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3477330834625238216-7147029327344114049?l=qemumemo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://qemumemo.blogspot.com/feeds/7147029327344114049/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://qemumemo.blogspot.com/2009/02/qemu-stdvga.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3477330834625238216/posts/default/7147029327344114049'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3477330834625238216/posts/default/7147029327344114049'/><link rel='alternate' type='text/html' href='http://qemumemo.blogspot.com/2009/02/qemu-stdvga.html' title='QEMU stdvga'/><author><name>aloha</name><uri>http://www.blogger.com/profile/17250121836567925230</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3477330834625238216.post-6470526357751546124</id><published>2009-02-05T10:56:00.001+09:00</published><updated>2009-02-05T10:58:41.630+09:00</updated><title type='text'>QEMU base emulator</title><content type='html'>&lt;a href="http://pylone.jp/blog/qemu_bishop_0.9.1_pylone1"&gt;Bishop エミュレータ&lt;/a&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;やはりこの会社は、Android もやってるみたい。&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3477330834625238216-6470526357751546124?l=qemumemo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://qemumemo.blogspot.com/feeds/6470526357751546124/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://qemumemo.blogspot.com/2009/02/qemu-base-emulator.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3477330834625238216/posts/default/6470526357751546124'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3477330834625238216/posts/default/6470526357751546124'/><link rel='alternate' type='text/html' href='http://qemumemo.blogspot.com/2009/02/qemu-base-emulator.html' title='QEMU base emulator'/><author><name>aloha</name><uri>http://www.blogger.com/profile/17250121836567925230</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3477330834625238216.post-6306673630031266433</id><published>2009-01-30T09:22:00.002+09:00</published><updated>2009-01-30T09:26:10.795+09:00</updated><title type='text'>parent_irq</title><content type='html'>QEMU の仮想デバイス (例えば i8259) には、parent_irq というメンバーが存在することが多い。&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;これにより、複数のデバイスの IRQ を繋げることができるようだ。なるほど、よくできてる。&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;大抵は、初期化の時に cpuirq などの、CPU と直結する IRQ （ハンドラの中で cpu_interrupt() を呼ぶ） を作っておいて、これをトップレベルの parent_irq とする。&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3477330834625238216-6306673630031266433?l=qemumemo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://qemumemo.blogspot.com/feeds/6306673630031266433/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://qemumemo.blogspot.com/2009/01/parentirq.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3477330834625238216/posts/default/6306673630031266433'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3477330834625238216/posts/default/6306673630031266433'/><link rel='alternate' type='text/html' href='http://qemumemo.blogspot.com/2009/01/parentirq.html' title='parent_irq'/><author><name>aloha</name><uri>http://www.blogger.com/profile/17250121836567925230</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3477330834625238216.post-2950764661852252591</id><published>2009-01-24T18:40:00.002+09:00</published><updated>2009-01-24T18:50:53.726+09:00</updated><title type='text'>ldl_code の続き</title><content type='html'>&lt;div&gt;grep しても見つからないわけだ。disas_arm_insn 内の ldl_code の正体は、例のこれ。&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;blockquote&gt;&lt;div&gt;#define ACCESS_TYPE (NB_MMU_MODES + 1)&lt;/div&gt;&lt;div&gt;#define MEMSUFFIX _code&lt;/div&gt;&lt;div&gt;#define env cpu_single_env&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;#define DATA_SIZE 1&lt;/div&gt;&lt;div&gt;#include "softmmu_header.h"&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;#define DATA_SIZE 2&lt;/div&gt;&lt;div&gt;#include "softmmu_header.h"&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;#define DATA_SIZE 4&lt;/div&gt;&lt;div&gt;#include "softmmu_header.h"&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;#define DATA_SIZE 8&lt;/div&gt;&lt;div&gt;#include "softmmu_header.h"&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;#undef ACCESS_TYPE&lt;/div&gt;&lt;div&gt;#undef MEMSUFFIX&lt;/div&gt;&lt;div&gt;#undef env&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;#endif&lt;/div&gt;&lt;/blockquote&gt;これで、softmmu_header.h 内の&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;blockquote&gt;&lt;div&gt;/* generic load/store macros */&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;static inline RES_TYPE glue(glue(ld, USUFFIX), MEMSUFFIX)(target_ulong ptr)&lt;/div&gt;&lt;div&gt;{&lt;/div&gt;&lt;div&gt;    int index;&lt;/div&gt;&lt;div&gt;    RES_TYPE res;&lt;/div&gt;&lt;div&gt;    target_ulong addr;&lt;/div&gt;&lt;div&gt;    unsigned long physaddr;&lt;/div&gt;&lt;div&gt;    int mmu_idx;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;    addr = ptr;&lt;/div&gt;&lt;div&gt;    index = (addr &gt;&gt; TARGET_PAGE_BITS) &amp;amp; (CPU_TLB_SIZE - 1);&lt;/div&gt;&lt;div&gt;    mmu_idx = CPU_MMU_INDEX;&lt;/div&gt;&lt;div&gt;    if (__builtin_expect(env-&gt;tlb_table[mmu_idx][index].ADDR_READ !=&lt;/div&gt;&lt;div&gt;                         (addr &amp;amp; (TARGET_PAGE_MASK | (DATA_SIZE - 1))), 0)) {&lt;/div&gt;&lt;div&gt;        res = glue(glue(__ld, SUFFIX), MMUSUFFIX)(addr, mmu_idx);&lt;/div&gt;&lt;div&gt;    } else {&lt;/div&gt;&lt;div&gt;        physaddr = addr + env-&gt;tlb_table[mmu_idx][index].addend;&lt;/div&gt;&lt;div&gt;        res = glue(glue(ld, USUFFIX), _raw)((uint8_t *)physaddr);&lt;/div&gt;&lt;div&gt;    }&lt;/div&gt;&lt;div&gt;    return res;&lt;/div&gt;&lt;div&gt;}&lt;/div&gt;&lt;/blockquote&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;これが tatic inline uint32_t  ldl_code(target_ulong ptr) に特殊化される。&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;blockquote&gt;&lt;div&gt;/* generic load/store macros */&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;static inline uint32_t ldl_code(target_ulong ptr)&lt;/div&gt;&lt;div&gt;{&lt;/div&gt;&lt;div&gt;    int index;&lt;/div&gt;&lt;div&gt;    uint32_t res;&lt;/div&gt;&lt;div&gt;    target_ulong addr;&lt;/div&gt;&lt;div&gt;    unsigned long physaddr;&lt;/div&gt;&lt;div&gt;    int mmu_idx;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;    addr = ptr;&lt;/div&gt;&lt;div&gt;    index = (addr &gt;&gt; TARGET_PAGE_BITS) &amp;amp; (CPU_TLB_SIZE - 1);&lt;/div&gt;&lt;div&gt;    mmu_idx = CPU_MMU_INDEX;&lt;/div&gt;&lt;div&gt;    if (__builtin_expect(env-&gt;tlb_table[mmu_idx][index].ADDR_READ !=&lt;/div&gt;&lt;div&gt;                         (addr &amp;amp; (TARGET_PAGE_MASK | (DATA_SIZE - 1))), 0)) {&lt;/div&gt;&lt;div&gt;        res = __ldl_cmmu(addr, mmu_idx);&lt;/div&gt;&lt;div&gt;    } else {&lt;/div&gt;&lt;div&gt;        physaddr = addr + env-&gt;tlb_table[mmu_idx][index].addend;&lt;/div&gt;&lt;div&gt;        res = ldl_raw((uint8_t *)physaddr);&lt;/div&gt;&lt;div&gt;    }&lt;/div&gt;&lt;div&gt;    return res;&lt;/div&gt;&lt;div&gt;}&lt;/div&gt;&lt;/blockquote&gt;&lt;/div&gt;&lt;/div&gt;考えてみれば当たり前。全ての (QEMU 上の仮想 RAM への) メモリアクセスは (QEMU の仮想) MMU 経由で行わないといけないのだから。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3477330834625238216-2950764661852252591?l=qemumemo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://qemumemo.blogspot.com/feeds/2950764661852252591/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://qemumemo.blogspot.com/2009/01/ldlcode.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3477330834625238216/posts/default/2950764661852252591'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3477330834625238216/posts/default/2950764661852252591'/><link rel='alternate' type='text/html' href='http://qemumemo.blogspot.com/2009/01/ldlcode.html' title='ldl_code の続き'/><author><name>aloha</name><uri>http://www.blogger.com/profile/17250121836567925230</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3477330834625238216.post-1441404021269365570</id><published>2009-01-23T11:01:00.004+09:00</published><updated>2009-01-24T18:36:10.268+09:00</updated><title type='text'>disas_arm_insn</title><content type='html'>target-arm/translate.c の&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;blockquote&gt;&lt;div&gt;static void disas_arm_insn(CPUState * env, DisasContext *s)&lt;/div&gt;&lt;div&gt;{&lt;/div&gt;&lt;div&gt;    unsigned int cond, insn, val, op1, i, shift, rm, rs, rn, rd, sh;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;    insn = ldl_code(s-&gt;pc);&lt;/div&gt;&lt;/blockquote&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;ここで s-&gt;pc は、ロードされたターゲットのマシン語の pc だ。&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;cpu-all.h を見ると。&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;blockquote&gt;&lt;div&gt;#define ldl_code(p) ldl_raw(p)&lt;/div&gt;&lt;div&gt;#define ldl_raw(p) ldl_p(laddr((p)))&lt;/div&gt;&lt;div&gt;#define laddr(x) (uint8_t *)(long)(x)&lt;/div&gt;&lt;div&gt;#define ldl_p(p) ldl_le_p(p)  /* !defined(TARGET_WORDS_BIGENDIAN)  */&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;static inline int ldl_le_p(void *ptr)&lt;/div&gt;&lt;div&gt;{&lt;/div&gt;&lt;div&gt;    return *(uint32_t *)ptr;&lt;/div&gt;&lt;div&gt;}&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/blockquote&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;う～ん、なぜこれで命令が取ってこれるのかよくわからない。&lt;/div&gt;&lt;div&gt;メモリのどこに、ターゲットの命令はロードされてるんだ ?&lt;/div&gt;&lt;div&gt;たぶん phys_ram_base とかだと思っていたんだけど、違うのかな ?&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;追記&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;これは CONFIG_USER_ONLY 版のコードなので、全く関係無かった。&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;しかし、どこに定義があるんだ… grep した限りでは見つけられなかった。&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3477330834625238216-1441404021269365570?l=qemumemo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://qemumemo.blogspot.com/feeds/1441404021269365570/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://qemumemo.blogspot.com/2009/01/disasarminsn.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3477330834625238216/posts/default/1441404021269365570'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3477330834625238216/posts/default/1441404021269365570'/><link rel='alternate' type='text/html' href='http://qemumemo.blogspot.com/2009/01/disasarminsn.html' title='disas_arm_insn'/><author><name>aloha</name><uri>http://www.blogger.com/profile/17250121836567925230</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3477330834625238216.post-2030099590056775451</id><published>2009-01-22T13:56:00.002+09:00</published><updated>2009-01-22T14:15:12.362+09:00</updated><title type='text'>cpu_index</title><content type='html'>exec.c の cpu_exec_init() を見ればわかるけど、全ての cpu_init()  (実体は cpu_arm_init() などの define) で作った CPU　(実体は target/ 以下の struct CPUARMState など) は、全てグローバル変数 first_cpu から作った順番に辿ることができる。&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;最初の CPU が cpu_index == 0 で、順番に全て番号が付いているので、番号で識別できる。&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;cpu_single_env も似たような感じに使われているけど、これは cpu-exec.c の cpu_exec 関数の内部だけで有効。&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;blockquote&gt;&lt;div&gt;686    /* fail safe : never use cpu_single_env outside cpu_exec() */&lt;/div&gt;&lt;div&gt;687    cpu_single_env = NULL;&lt;/div&gt;&lt;div&gt;688    return ret;&lt;/div&gt;&lt;div&gt;689}&lt;/div&gt;&lt;/blockquote&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;ここらへんからも、QEMU はマルチスレッド対応が考えられていないことがわかる。&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;blockquote&gt;&lt;div&gt;/* 'pc' is the host PC at which the exception was raised. 'address' is&lt;/div&gt;&lt;div&gt;   the effective address of the memory exception. 'is_write' is 1 if a&lt;/div&gt;&lt;div&gt;   write caused the exception and otherwise 0'. 'old_set' is the&lt;/div&gt;&lt;div&gt;   signal set which should be restored */&lt;/div&gt;&lt;div&gt;static inline int handle_cpu_signal(unsigned long pc, unsigned long address,&lt;/div&gt;&lt;div&gt;                                    int is_write, sigset_t *old_set,&lt;/div&gt;&lt;div&gt;                                    void *puc)&lt;/div&gt;&lt;div&gt;{&lt;/div&gt;&lt;div&gt;    TranslationBlock *tb;&lt;/div&gt;&lt;div&gt;    int ret;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;    if (cpu_single_env)&lt;/div&gt;&lt;div&gt;        env = cpu_single_env; /* XXX: find a correct solution for multithread */&lt;/div&gt;&lt;/blockquote&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3477330834625238216-2030099590056775451?l=qemumemo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://qemumemo.blogspot.com/feeds/2030099590056775451/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://qemumemo.blogspot.com/2009/01/cpuindex.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3477330834625238216/posts/default/2030099590056775451'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3477330834625238216/posts/default/2030099590056775451'/><link rel='alternate' type='text/html' href='http://qemumemo.blogspot.com/2009/01/cpuindex.html' title='cpu_index'/><author><name>aloha</name><uri>http://www.blogger.com/profile/17250121836567925230</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3477330834625238216.post-2850447740144021366</id><published>2009-01-19T16:39:00.002+09:00</published><updated>2009-01-19T16:41:26.229+09:00</updated><title type='text'>cpu_interrpt() is probably not threadsafe.</title><content type='html'>う～む。&lt;br /&gt;&lt;blockquote&gt;&lt;div&gt;/* mask must never be zero, except for A20 change call */&lt;/div&gt;&lt;div&gt;void cpu_interrupt(CPUState *env, int mask)&lt;/div&gt;&lt;div&gt;{&lt;/div&gt;&lt;div&gt;。。。&lt;/div&gt;&lt;div&gt;    /* FIXME: This is probably not threadsafe.  A different thread could&lt;/div&gt;&lt;div&gt;       be in the middle of a read-modify-write operation.  */&lt;/div&gt;&lt;div&gt;    env-&gt;interrupt_request |= mask;&lt;/div&gt;&lt;div&gt;#if defined(USE_NPTL)&lt;/div&gt;&lt;div&gt;    /* FIXME: TB unchaining isn't SMP safe.  For now just ignore the&lt;/div&gt;&lt;div&gt;       problem and hope the cpu will stop of its own accord.  For userspace&lt;/div&gt;&lt;div&gt;       emulation this often isn't actually as bad as it sounds.  Often&lt;/div&gt;&lt;div&gt;       signals are used primarily to interrupt blocking syscalls.  */&lt;/div&gt;&lt;div&gt;#else&lt;/div&gt;&lt;div&gt;       。。。&lt;/div&gt;&lt;div&gt;}&lt;/div&gt;&lt;/blockquote&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3477330834625238216-2850447740144021366?l=qemumemo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://qemumemo.blogspot.com/feeds/2850447740144021366/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://qemumemo.blogspot.com/2009/01/cpuinterrpt-is-probably-not-threadsafe.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3477330834625238216/posts/default/2850447740144021366'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3477330834625238216/posts/default/2850447740144021366'/><link rel='alternate' type='text/html' href='http://qemumemo.blogspot.com/2009/01/cpuinterrpt-is-probably-not-threadsafe.html' title='cpu_interrpt() is probably not threadsafe.'/><author><name>aloha</name><uri>http://www.blogger.com/profile/17250121836567925230</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3477330834625238216.post-5325538127636383074</id><published>2009-01-19T15:45:00.003+09:00</published><updated>2009-01-19T16:20:48.594+09:00</updated><title type='text'>QEMU internal timer interrupts</title><content type='html'>&lt;div&gt;cpu_exec の内部では、TB (TranslationBlock) の実行ループが延々と行われている （TB には、ブレークポイントやジャンプ命令は入っていないので、無限ループを実行中でも必ず止まる。止まっては、また実行し、の繰り返し）。&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;しかし、これだけでは、仮想 CPU の上でエミュレートしている外部ペリフェラル （= 実行中のプログラム） などから割り込みが入らない限り、QEMU の内部の時間を進めることができなくなってしまう。&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;そこで QEMU は、自ら定期的に割り込み （CPU_INTERRUPT_EXIT） を CPU に入れることにより、cpu_exec 内部の TB （JIT 済みのコード）実行ループから抜けているようだ。これで、QEMU 内部の時間が進み、様々な内部処理を一定間隔で行うことが可能になる。&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;つまり、TB チェーンの実行を繰り返す小さなループと、定期的に割り込みをチェックして、割り込み要因に合わせて CPU の状態を変化させるための大きなループの、2 つのループが回っている。&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;div&gt;exec.c に以下のようなコメントがある。&lt;br /&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;blockquote&gt;&lt;div&gt;        /* CPU_INTERRUPT_EXIT isn't a real interrupt.  It just means&lt;/div&gt;&lt;div&gt;           an async event happened and we need to process it.  */&lt;/div&gt;&lt;/blockquote&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;大きいほうのループを動かすため、小さいほうのループに定期的に割り込みを入れる際には、Windows のマルチメディアタイマーを使用しているようだ。&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Windows 対応 patch の開発者の方のブログ記事。&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;a href="http://blogs.dion.ne.jp/kazuu/archives/2544632.html"&gt;http://blogs.dion.ne.jp/kazuu/archives/2544632.html&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;a href="http://blogs.dion.ne.jp/kazuu/archives/3127029.html"&gt;http://blogs.dion.ne.jp/kazuu/archives/3127029.html&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;（核心部分）&lt;/div&gt;&lt;div&gt;&lt;a href="http://blogs.dion.ne.jp/kazuu/archives/3132263.html"&gt;http://blogs.dion.ne.jp/kazuu/archives/3132263.html&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;このほかにもたくさん参考になる記事があって、ゲスト OS の時計の進め方を正確にしようと思うと、非常に大変ということがよくわかる。&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;vl.c を使う （普通に QEMU システム全体を使う） 場合は考えなくても良いけど、仮想 CPU ライブラリ (libqemu.a） の部分だけを使う場合は、ここらへんも考えないとちゃんと動かない。&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;ちょっと気になった記事。デバッガと繋げる際のはまりポイント。&lt;/div&gt;&lt;div&gt;&lt;a href="http://blogs.dion.ne.jp/kazuu/archives/3890764.html"&gt;http://blogs.dion.ne.jp/kazuu/archives/3890764.html&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3477330834625238216-5325538127636383074?l=qemumemo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://qemumemo.blogspot.com/feeds/5325538127636383074/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://qemumemo.blogspot.com/2009/01/qemu-internal-timer-interrupts.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3477330834625238216/posts/default/5325538127636383074'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3477330834625238216/posts/default/5325538127636383074'/><link rel='alternate' type='text/html' href='http://qemumemo.blogspot.com/2009/01/qemu-internal-timer-interrupts.html' title='QEMU internal timer interrupts'/><author><name>aloha</name><uri>http://www.blogger.com/profile/17250121836567925230</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3477330834625238216.post-2003583065253249857</id><published>2009-01-15T09:49:00.002+09:00</published><updated>2009-01-15T09:57:25.068+09:00</updated><title type='text'>trunk</title><content type='html'>QEMU の Subversion から &lt;a href="http://svn.savannah.gnu.org/viewvc?view=rev&amp;amp;root=qemu&amp;amp;revision=6292"&gt;trunk (6292) &lt;/a&gt; を取ってきたら、cc も host-cc も共に、 gcc 3 系列でも 4 系列でも無修正でビルド通って、正常に動いているようだ。素晴らしい。&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;blockquote&gt;&lt;div&gt;$ &lt;span class="Apple-style-span" style="font-family: -webkit-monospace; font-size: 13px; "&gt;svn co svn://svn.sv.gnu.org/qemu&lt;/span&gt;&lt;/div&gt;&lt;div&gt;$ cd ..&lt;/div&gt;&lt;div&gt;$ mkdir build&lt;/div&gt;&lt;div&gt;$ cd build&lt;/div&gt;&lt;div&gt;&lt;div&gt;$ i686-pc-mingw32-gcc-4.3.2.exe -v&lt;/div&gt;&lt;div&gt;Using built-in specs.&lt;/div&gt;&lt;div&gt;Target: i686-pc-mingw32&lt;/div&gt;&lt;div&gt;Configured with: ../gcc-4.3.2/configure --with-as=/usr/local/bin/as --with-ld=/usr/local/bin/ld --with-gmp=/usr/local --with-mpfr=/usr/local --enable-languages=c,c++ --enable-threads --disable-nls --disable-win32-registry --disable-shared --without-x --enable-hash-synchronization --enable-libstdcxx-debug --enable-version-specific-runtime-libs --without-included-gettext --disable-bootstrap --disable-libssp --disable-libstdcxx-pch&lt;/div&gt;&lt;div&gt;Thread model: win32&lt;/div&gt;&lt;div&gt;gcc version 4.3.2 (GCC)&lt;/div&gt;&lt;/div&gt;&lt;div&gt;$ ../trunk/configure --cc=i686-pc-mingw32-gcc-4.3.2.exe --host-cc=i686-pc-&lt;/div&gt;&lt;div&gt;mingw32-gcc-4.3.2.exe --target-list=arm-softmmu&lt;/div&gt;&lt;div&gt;$ make&lt;/div&gt;&lt;div&gt;$ cd ..&lt;/div&gt;&lt;div&gt;$ wget http://bellard.org/qemu/arm-test-0.2.tar.gz&lt;br /&gt;&lt;/div&gt;&lt;div&gt;$ tar zxvf arm-test-0.2.tar.gz&lt;br /&gt;&lt;/div&gt;&lt;div&gt;$ cd arm-test&lt;/div&gt;&lt;div&gt;$ ../build/arm-softmmu/qemu-system-arm.exe -kernel zImage.integrator -initrd arm_root.img&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/blockquote&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3477330834625238216-2003583065253249857?l=qemumemo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://qemumemo.blogspot.com/feeds/2003583065253249857/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://qemumemo.blogspot.com/2009/01/trunk.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3477330834625238216/posts/default/2003583065253249857'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3477330834625238216/posts/default/2003583065253249857'/><link rel='alternate' type='text/html' href='http://qemumemo.blogspot.com/2009/01/trunk.html' title='trunk'/><author><name>aloha</name><uri>http://www.blogger.com/profile/17250121836567925230</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3477330834625238216.post-2824893347570484081</id><published>2009-01-14T16:47:00.003+09:00</published><updated>2009-01-14T17:03:14.618+09:00</updated><title type='text'>softmmu_template</title><content type='html'>template というから、なんか自動生成しているのかと思っていたら、何のことは無かった。&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;単にプリプロセッサで切り替えているだけだった。&lt;/div&gt;&lt;div&gt;exec.c の一番最後。&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;blockquote&gt;&lt;div&gt;#if !defined(CONFIG_USER_ONLY)&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;#define MMUSUFFIX _cmmu&lt;/div&gt;&lt;div&gt;#define GETPC() NULL&lt;/div&gt;&lt;div&gt;#define env cpu_single_env&lt;/div&gt;&lt;div&gt;#define SOFTMMU_CODE_ACCESS&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;#define SHIFT 0&lt;/div&gt;&lt;div&gt;#include "softmmu_template.h"&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;#define SHIFT 1&lt;/div&gt;&lt;div&gt;#include "softmmu_template.h"&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;#define SHIFT 2&lt;/div&gt;&lt;div&gt;#include "softmmu_template.h"&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;#define SHIFT 3&lt;/div&gt;&lt;div&gt;#include "softmmu_template.h"&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;#undef env&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;#endif&lt;/div&gt;&lt;/blockquote&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;softmmu_template.h&lt;/div&gt;&lt;div&gt;&lt;blockquote&gt;&lt;div&gt;#define DATA_SIZE (1 &lt;&lt;&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;#if DATA_SIZE == 8&lt;/div&gt;&lt;div&gt;#define SUFFIX q&lt;/div&gt;&lt;div&gt;#define USUFFIX q&lt;/div&gt;&lt;div&gt;#define DATA_TYPE uint64_t&lt;/div&gt;&lt;div&gt;#elif DATA_SIZE == 4&lt;/div&gt;&lt;div&gt;#define SUFFIX l&lt;/div&gt;&lt;div&gt;#define USUFFIX l&lt;/div&gt;&lt;div&gt;#define DATA_TYPE uint32_t&lt;/div&gt;&lt;div&gt;#elif DATA_SIZE == 2&lt;/div&gt;&lt;div&gt;#define SUFFIX w&lt;/div&gt;&lt;div&gt;#define USUFFIX uw&lt;/div&gt;&lt;div&gt;#define DATA_TYPE uint16_t&lt;/div&gt;&lt;div&gt;#elif DATA_SIZE == 1&lt;/div&gt;&lt;div&gt;#define SUFFIX b&lt;/div&gt;&lt;div&gt;#define USUFFIX ub&lt;/div&gt;&lt;div&gt;#define DATA_TYPE uint8_t&lt;/div&gt;&lt;div&gt;#else&lt;/div&gt;&lt;div&gt;#error unsupported data size&lt;/div&gt;&lt;div&gt;#endif&lt;/div&gt;&lt;/div&gt;&lt;/blockquote&gt;要するに、0 が byte (uint8_t)、1 が word (uint16_t)、2 が long (uint32_t)、3 が quad word (uint64_t) ということらしい。&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;blockquote&gt;&lt;div&gt;#if SHIFT &lt;= 2&lt;/div&gt;&lt;div&gt;    io_mem_write[index][SHIFT](io_mem_opaque[index], physaddr, val);&lt;/div&gt;&lt;/blockquote&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;みたいになっていて、0-1 (byte,word,long) それぞれのハンドラがコールされる。なるほど。&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;quad word の場合は、エンディアンに合わせて long (io_mem*[2]) のハンドラを 2 回コール。&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3477330834625238216-2824893347570484081?l=qemumemo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://qemumemo.blogspot.com/feeds/2824893347570484081/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://qemumemo.blogspot.com/2009/01/softmmutemplate.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3477330834625238216/posts/default/2824893347570484081'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3477330834625238216/posts/default/2824893347570484081'/><link rel='alternate' type='text/html' href='http://qemumemo.blogspot.com/2009/01/softmmutemplate.html' title='softmmu_template'/><author><name>aloha</name><uri>http://www.blogger.com/profile/17250121836567925230</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3477330834625238216.post-53793267940771926</id><published>2009-01-13T12:14:00.003+09:00</published><updated>2009-01-13T12:37:21.809+09:00</updated><title type='text'>global variables</title><content type='html'>io メモリの実体は exec.c に。&lt;br /&gt;&lt;div&gt;&lt;/div&gt;&lt;blockquote&gt;&lt;div&gt;CPUWriteMemoryFunc *io_mem_write[IO_MEM_NB_ENTRIES][4];&lt;/div&gt;&lt;div&gt;CPUReadMemoryFunc *io_mem_read[IO_MEM_NB_ENTRIES][4];&lt;/div&gt;&lt;div&gt;void *io_mem_opaque[IO_MEM_NB_ENTRIES];&lt;/div&gt;&lt;/blockquote&gt;&lt;div&gt;&lt;/div&gt;物理メモリの実体は、ポインタが exec.c にあって、&lt;br /&gt;&lt;blockquote&gt;int phys_ram_size;&lt;br /&gt;uint8_t *phys_ram_base;&lt;/blockquote&gt;&lt;br /&gt;vl.c で確保される。&lt;br /&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;blockquote&gt;&lt;div&gt;    /* init the memory */&lt;/div&gt;&lt;div&gt;    phys_ram_size = ram_size + vga_ram_size + MAX_BIOS_SIZE;&lt;/div&gt;&lt;div&gt;    phys_ram_base = qemu_vmalloc(phys_ram_size);&lt;/div&gt;&lt;/blockquote&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;qemu_vmalloc(size) は osdep.c で定義されており、Windows の場合は VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_READWRITE) が使われる。&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3477330834625238216-53793267940771926?l=qemumemo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://qemumemo.blogspot.com/feeds/53793267940771926/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://qemumemo.blogspot.com/2009/01/global-variable.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3477330834625238216/posts/default/53793267940771926'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3477330834625238216/posts/default/53793267940771926'/><link rel='alternate' type='text/html' href='http://qemumemo.blogspot.com/2009/01/global-variable.html' title='global variables'/><author><name>aloha</name><uri>http://www.blogger.com/profile/17250121836567925230</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3477330834625238216.post-4479037241480818229</id><published>2009-01-13T09:39:00.002+09:00</published><updated>2009-01-13T11:10:02.776+09:00</updated><title type='text'>io_memory</title><content type='html'>&lt;div&gt;cpu_register_io_memory が返す整数値は、io メモリ配列の index に関連付けられたディスクリプタ&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;blockquote&gt;&lt;div&gt;int cpu_register_io_memory(int io_index,&lt;/div&gt;&lt;div&gt;                           CPUReadMemoryFunc **mem_read,&lt;/div&gt;&lt;div&gt;                           CPUWriteMemoryFunc **mem_write,&lt;/div&gt;&lt;div&gt;                           void *opaque)&lt;/div&gt;&lt;div&gt;{&lt;/div&gt;&lt;div&gt;    int i, subwidth = 0;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;    if (io_index &lt;= 0) {&lt;/div&gt;&lt;div&gt;        if (io_mem_nb &gt;= IO_MEM_NB_ENTRIES)&lt;/div&gt;&lt;div&gt;            return -1;&lt;/div&gt;&lt;div&gt;        io_index = io_mem_nb++;&lt;/div&gt;&lt;div&gt;    } else {&lt;/div&gt;&lt;div&gt;        if (io_index &gt;= IO_MEM_NB_ENTRIES)&lt;/div&gt;&lt;div&gt;            return -1;&lt;/div&gt;&lt;div&gt;    }&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;    for(i = 0;i &lt;&gt;&lt;div&gt;        if (!mem_read[i] || !mem_write[i])&lt;/div&gt;&lt;div&gt;            subwidth = IO_MEM_SUBWIDTH;&lt;/div&gt;&lt;div&gt;        io_mem_read[io_index][i] = mem_read[i];&lt;/div&gt;&lt;div&gt;        io_mem_write[io_index][i] = mem_write[i];&lt;/div&gt;&lt;div&gt;    }&lt;/div&gt;&lt;div&gt;    io_mem_opaque[io_index] = opaque;&lt;/div&gt;&lt;div&gt;    return (io_index &lt;&lt;&gt;&lt;div&gt;}&lt;/div&gt;&lt;/blockquote&gt;&lt;div&gt;&lt;/div&gt;io_index を IO_MEM_SHIFT ぶん右シフトしたものが、io_mem* 配列の index になる。&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;blockquote&gt;&lt;div&gt;CPUWriteMemoryFunc **cpu_get_io_memory_write(int io_index)&lt;/div&gt;&lt;div&gt;{&lt;/div&gt;&lt;div&gt;    return io_mem_write[io_index &gt;&gt; IO_MEM_SHIFT];&lt;/div&gt;&lt;div&gt;}&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;CPUReadMemoryFunc **cpu_get_io_memory_read(int io_index)&lt;/div&gt;&lt;div&gt;{&lt;/div&gt;&lt;div&gt;  &lt;br /&gt; return io_mem_read[io_index &gt;&gt; IO_MEM_SHIFT];&lt;/div&gt;&lt;div&gt;}&lt;/div&gt;&lt;/blockquote&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;io メモリ配列の 0、1、2、4 は、それぞれ RAM、ROM、UNASSIGNED、NOTDIRTY に決め打たれているので、io_mem_nb は 5 からスタート。&lt;/div&gt;&lt;div&gt;static void io_mem_init(void)&lt;/div&gt;&lt;div&gt;{&lt;/div&gt;&lt;div&gt;    cpu_register_io_memory(IO_MEM_ROM &gt;&gt; IO_MEM_SHIFT, error_mem_read, unassigned_mem_write, NULL);&lt;/div&gt;&lt;div&gt;    cpu_register_io_memory(IO_MEM_UNASSIGNED &gt;&gt; IO_MEM_SHIFT, unassigned_mem_read, unassigned_mem_write, NULL);&lt;/div&gt;&lt;div&gt;    cpu_register_io_memory(IO_MEM_NOTDIRTY &gt;&gt; IO_MEM_SHIFT, error_mem_read, notdirty_mem_write, NULL);&lt;/div&gt;&lt;div&gt;    io_mem_nb = 5;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;#if defined(CONFIG_SOFTMMU)&lt;/div&gt;&lt;div&gt;    io_mem_watch = cpu_register_io_memory(-1, watch_mem_read,&lt;/div&gt;&lt;div&gt;                                          watch_mem_write, NULL);&lt;/div&gt;&lt;div&gt;#endif&lt;/div&gt;&lt;div&gt;    /* alloc dirty bits array */&lt;/div&gt;&lt;div&gt;    phys_ram_dirty = qemu_vmalloc(phys_ram_size &gt;&gt; TARGET_PAGE_BITS);&lt;/div&gt;&lt;div&gt;    memset(phys_ram_dirty, 0xff, phys_ram_size &gt;&gt; TARGET_PAGE_BITS);&lt;/div&gt;&lt;div&gt;}&lt;/div&gt;&lt;/div&gt;&lt;div&gt;io メモリ配列は最大 IO_MEM_NB_ENTRIES 個で、最後の要素の index + 1 が io_mem_nb 変数。&lt;/div&gt;&lt;div&gt;exec.c&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;blockquote&gt;&lt;div&gt;/* io memory support */&lt;/div&gt;&lt;div&gt;CPUWriteMemoryFunc *io_mem_write[IO_MEM_NB_ENTRIES][4];&lt;/div&gt;&lt;div&gt;CPUReadMemoryFunc *io_mem_read[IO_MEM_NB_ENTRIES][4];&lt;/div&gt;&lt;div&gt;void *io_mem_opaque[IO_MEM_NB_ENTRIES];&lt;/div&gt;&lt;div&gt;static int io_mem_nb;&lt;/div&gt;&lt;div&gt;#if defined(CONFIG_SOFTMMU)&lt;/div&gt;&lt;div&gt;static int io_mem_watch;&lt;/div&gt;&lt;div&gt;#endif&lt;/div&gt;&lt;/blockquote&gt;cpu-all.h&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;blockquote&gt;&lt;div&gt;&lt;div&gt;/* physical memory access */&lt;/div&gt;&lt;div&gt;#define TLB_INVALID_MASK   (1 &lt;&lt;&gt;&lt;div&gt;#define IO_MEM_SHIFT       4&lt;/div&gt;&lt;div&gt;#define IO_MEM_NB_ENTRIES  (1 &lt;&lt; (TARGET_PAGE_BITS  - IO_MEM_SHIFT))&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;#define IO_MEM_RAM         (0 &lt;&lt;&gt;&lt;div&gt;#define IO_MEM_ROM         (1 &lt;&lt;&gt;&lt;div&gt;#define IO_MEM_UNASSIGNED  (2 &lt;&lt;&gt;&lt;div&gt;#define IO_MEM_NOTDIRTY    (4 &lt;&lt;&gt;&lt;div&gt;/* acts like a ROM when read and like a device when written. As an&lt;/div&gt;&lt;div&gt;   exception, the write memory callback gets the ram offset instead of&lt;/div&gt;&lt;div&gt;   the physical address */&lt;/div&gt;&lt;div&gt;#define IO_MEM_ROMD        (1)&lt;/div&gt;&lt;div&gt;#define IO_MEM_SUBPAGE     (2)&lt;/div&gt;&lt;div&gt;#define IO_MEM_SUBWIDTH    (4)&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/blockquote&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;target-arm/cpu.h&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;blockquote&gt;&lt;div&gt;#if defined(CONFIG_USER_ONLY)&lt;/div&gt;&lt;div&gt;#define TARGET_PAGE_BITS 12&lt;/div&gt;&lt;div&gt;#else&lt;/div&gt;&lt;div&gt;/* The ARM MMU allows 1k pages.  */&lt;/div&gt;&lt;div&gt;/* ??? Linux doesn't actually use these, and they're deprecated in recent&lt;/div&gt;&lt;div&gt;   architecture revisions.  Maybe a configure option to disable them.  */&lt;/div&gt;&lt;div&gt;#define TARGET_PAGE_BITS 10&lt;/div&gt;&lt;div&gt;#endif&lt;/div&gt;&lt;/blockquote&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;通常は TARGET_PAGE_BITS が 10 なので IO_MEM_NB_ENTRIES は 64 かな。&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;物理メモリを割り付ける際には、cpu_register_physical_memory(0, ram_size, IO_MEM_RAM); のように、phys_offset を指定して呼び出すが、これが (phys_offset &amp;amp; ~TARGET_PAGE_MASK) != 0 の場合 io memory page と見なされ、start_addr から size までの範囲に io_mem*&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;TARGET_MAGE_MASK は&lt;/div&gt;&lt;div&gt;&lt;div&gt;cpu-all.h&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;blockquote&gt;&lt;div&gt;#define TARGET_PAGE_SIZE (1 &lt;&lt;&gt;&lt;div&gt;#define TARGET_PAGE_MASK ~(TARGET_PAGE_SIZE - 1)&lt;/div&gt;&lt;/div&gt;&lt;/blockquote&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;TARGET_PAGE_SIZE が 1024 で、TARGET_PAGE_MASK は 0 ～ 9 ビット目までのマスク。&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;実際に page に io_memory を関連付けるのは、subpage_register()。&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;blockquote&gt;&lt;div&gt;static int subpage_register (subpage_t *mmio, uint32_t start, uint32_t end,&lt;/div&gt;&lt;div&gt;                             int memory)&lt;/div&gt;&lt;div&gt;{&lt;/div&gt;&lt;div&gt;    int idx, eidx;&lt;/div&gt;&lt;div&gt;    unsigned int i;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;    if (start &gt;= TARGET_PAGE_SIZE || end &gt;= TARGET_PAGE_SIZE)&lt;/div&gt;&lt;div&gt;        return -1;&lt;/div&gt;&lt;div&gt;    idx = SUBPAGE_IDX(start);&lt;/div&gt;&lt;div&gt;    eidx = SUBPAGE_IDX(end);&lt;/div&gt;&lt;div&gt;#if defined(DEBUG_SUBPAGE)&lt;/div&gt;&lt;div&gt;    printf("%s: %p start %08x end %08x idx %08x eidx %08x mem %d\n", __func__,&lt;/div&gt;&lt;div&gt;           mmio, start, end, idx, eidx, memory);&lt;/div&gt;&lt;div&gt;#endif&lt;/div&gt;&lt;div&gt;    memory &gt;&gt;= IO_MEM_SHIFT;&lt;/div&gt;&lt;div&gt;    for (; idx &lt;= eidx; idx++) {&lt;/div&gt;&lt;div&gt;        for (i = 0; i &lt;&gt;&lt;div&gt;            if (io_mem_read[memory][i]) {&lt;/div&gt;&lt;div&gt;                mmio-&gt;mem_read[idx][i] = &amp;amp;io_mem_read[memory][i];&lt;/div&gt;&lt;div&gt;                mmio-&gt;opaque[idx][0][i] = io_mem_opaque[memory];&lt;/div&gt;&lt;div&gt;            }&lt;/div&gt;&lt;div&gt;            if (io_mem_write[memory][i]) {&lt;/div&gt;&lt;div&gt;                mmio-&gt;mem_write[idx][i] = &amp;amp;io_mem_write[memory][i];&lt;/div&gt;&lt;div&gt;                mmio-&gt;opaque[idx][1][i] = io_mem_opaque[memory];&lt;/div&gt;&lt;div&gt;            }&lt;/div&gt;&lt;div&gt;        }&lt;/div&gt;&lt;div&gt;    }&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;    return 0;&lt;/div&gt;&lt;div&gt;}&lt;/div&gt;&lt;/div&gt;&lt;/blockquote&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;subpage というのは、おそらく、通常のメモリページ以外のページ (io page など) という意味だと思う。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3477330834625238216-4479037241480818229?l=qemumemo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://qemumemo.blogspot.com/feeds/4479037241480818229/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://qemumemo.blogspot.com/2009/01/iomemory.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3477330834625238216/posts/default/4479037241480818229'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3477330834625238216/posts/default/4479037241480818229'/><link rel='alternate' type='text/html' href='http://qemumemo.blogspot.com/2009/01/iomemory.html' title='io_memory'/><author><name>aloha</name><uri>http://www.blogger.com/profile/17250121836567925230</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3477330834625238216.post-4244491187916877365</id><published>2009-01-08T09:43:00.003+09:00</published><updated>2009-01-08T11:21:17.705+09:00</updated><title type='text'>CPU から I/O 空間 （タイマー） へのアクセス</title><content type='html'>QEMU では、特定のアドレスにコールバックが結び付けてあって、I/O 空間にアクセスする。&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;具体的には、I/O メモリにアクセスすると cpu_register_io_memory() に渡したコールバックが実行される。&lt;br /&gt;&lt;/div&gt;&lt;blockquote&gt;&lt;div&gt;&lt;div&gt;/* mem_read と mem_write は、byte にアクセスするための関数 (mem_*[0])、&lt;br /&gt;word にアクセスするための関数 (mem_*[1])、そして double word にアクセス&lt;br /&gt;するための関数の配列。関数は NULL 関数ポインタで省略することができる。&lt;br /&gt;登録済みの関数は、後で動的に変更される可能性がある。&lt;br /&gt;もし io_index が非ゼロならば、対応する I/O ゾーンが変更される。もしゼロならば、&lt;br /&gt;新しい I/O ゾーンがアロケートされる。戻り値は cpu_register_physical_memory()&lt;br /&gt;とともに使用することができる。もしエラーの場合は -1 が返る。*/&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;int cpu_register_io_memory(int io_index,&lt;br /&gt;CPUReadMemoryFunc **mem_read, CPUWriteMemoryFunc **mem_write,&lt;br /&gt;void *opaque);&lt;/div&gt;&lt;/div&gt;&lt;/blockquote&gt;&lt;div&gt;&lt;div&gt;つまり、全てのメモリアクセスについて、通常のメモリアクセスと I/O メモリのアクセスを判定して、適切に扱われないといけない。&lt;br /&gt;&lt;br /&gt;QEMU は JIT 実行を行うので、コールバックを呼び出すためのコードを生成する必要がある。&lt;br /&gt;&lt;br /&gt;そのやり方が、けっこう面倒なことをしているのでメモ。&lt;br /&gt;&lt;br /&gt;まず、論文を読む。だいたいのことが書いてある。&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.usenix.org/publications/library/proceedings/usenix05/tech/freenix/bellard.html"&gt;QEMU, a Fast and Portable Dynamic Translator&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;現在のリリース最新版 QEMU (0.9.1) の JIT は、&lt;br /&gt;&lt;ol&gt;&lt;li&gt;ターゲットマシン命令 （のマイクロオペレーション） をエミュレートする C コード片を書く&lt;/li&gt;&lt;li&gt;GCC でコンパイルして、ホストマシン向けのオブジェクトファイルを作る (dyngen は ELF/PE-COFF/MACH-O  に対応)&lt;br /&gt;&lt;/li&gt;&lt;li&gt;オブジェクトファイルを dyngen で解析し、ターゲットマシン命令からマイクロオペレーション （ホストマシン命令列） トランスレータが include するヘッダを自動生成する&lt;/li&gt;&lt;/ol&gt;&lt;ul&gt;&lt;li&gt;命令に対応する関数のオブジェクトファイル中の位置などを記録したヘッダ&lt;/li&gt;&lt;li&gt;オブジェクトファイルの対応位置から命令列をバッファにコピーするコードが生成されたヘッダ (トランスレータ本体)&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;という、非常に斬新なやり方で実現されている。&lt;br /&gt;&lt;br /&gt;（しかし、そのせいで、GCC の 3.x でしかちゃんと動かないという縛りができてしまっている。trunk のヘッドでは、Tiny Code Generator (TCG) という新しい JIT に差し替えられている）&lt;br /&gt;&lt;br /&gt;ここのところが、プリプロセッサやトランスレータを駆使したコードの自動生成が行われまくるので、わかりにくい。&lt;br /&gt;&lt;br /&gt;QEMU のビルドディレクトリの、例えば  arm-softmmu などの下に自動生成されたヘッダファイル (op.h/gen-op.h/opc.h) が存在するので、確認。&lt;br /&gt;&lt;br /&gt;ARM の store 命令を x86 命令列に JIT する時には、gen_op_stl_kernel などが呼ばれて、オペコード列が作られる (gen-op.h)。&lt;br /&gt;&lt;blockquote&gt;static inline void gen_op_stl_kernel(void)&lt;br /&gt;{&lt;br /&gt;  *gen_opc_ptr++ = INDEX_op_stl_kernel;&lt;br /&gt;}&lt;/blockquote&gt;&lt;br /&gt;オペコード列から、最終的な x86 命令列が作られる。その対応表が opc.h。&lt;br /&gt;&lt;br /&gt;opc.h には&lt;br /&gt;&lt;blockquote&gt;...&lt;br /&gt;DEF(stl_user, 0, 80)&lt;br /&gt;...&lt;br /&gt;DEF(stl_kernel, 0, 72)&lt;/blockquote&gt;のようになっている。stl_kernel は、store long の kernel モード時の命令に対応する。72 は、オブジェクトファイル中の関数のサイズ。&lt;br /&gt;これらはトランスレータ本体 translater.c の中で使われる。&lt;br /&gt;&lt;blockquote&gt;enum {&lt;br /&gt;#define DEF(s, n, copy_size) INDEX_op_ ## s,&lt;br /&gt;#include "opc.h"&lt;br /&gt;#undef DEF&lt;br /&gt;  NB_OPS,&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;#include "gen-op.h"&lt;/blockquote&gt;&lt;br /&gt;そして最終的に op.h では&lt;br /&gt;&lt;blockquote&gt;case INDEX_op_stl_kernel: {&lt;br /&gt;  extern void op_stl_kernel();&lt;br /&gt;extern char __stl_mmu;&lt;br /&gt;  memcpy(gen_code_ptr, (void *)((char *)&amp;amp;op_stl_kernel+0), 72);&lt;br /&gt;  *(uint32_t *)(gen_code_ptr + 46) = (long)(&amp;amp;__stl_mmu) - (long)(gen_code_ptr + 46) + 0 -4;&lt;br /&gt;  gen_code_ptr += 72;&lt;br /&gt;}&lt;br /&gt;break;&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;のように、オブジェクトファイルからバッファの gen_code_ptr 位置に 72 バイトコピーし、___stl_mmu() 関数呼び出しのアドレスを差し替えている。&lt;br /&gt;&lt;br /&gt;つまり、バッファの JIT 済みのコードの先頭にジャンプして実行された時、___ldl_mmu() が呼ばれて、その中でメモリの種類の判定や、コールバックの呼び出しなどが行われている。&lt;br /&gt;&lt;br /&gt;___stl_mmu なんていう関数の定義は grep しても見つからない。プリプロセッサマクロで関数名が自動生成されている。MMUSUFFIX は softmmu_header.h で定義される。&lt;br /&gt;&lt;br /&gt;本体は softmmu_template.h にある。その名のとおりのテンプレートで、アクセスする型のサイズや MMU の種類に応じて関数名が作られる。glue はプリプロセッサでシンボルをくっつけているだけ (foo ## 1 == glue(foo, 1) == foo1)&lt;br /&gt;&lt;blockquote&gt;void REGPARM(2) glue(glue(__st, SUFFIX), MMUSUFFIX)(target_ulong addr,&lt;br /&gt;                                                  DATA_TYPE val,&lt;br /&gt;                                                  int mmu_idx)&lt;br /&gt;{&lt;br /&gt;  target_phys_addr_t physaddr;&lt;br /&gt;  target_ulong tlb_addr;&lt;br /&gt;  void *retaddr;&lt;br /&gt;  int index;&lt;br /&gt;&lt;br /&gt;  index = (addr &gt;&gt; TARGET_PAGE_BITS) &amp;amp; (CPU_TLB_SIZE - 1);&lt;br /&gt;redo:&lt;br /&gt;  tlb_addr = env-&gt;tlb_table[mmu_idx][index].addr_write;&lt;br /&gt;  if ((addr &amp;amp; TARGET_PAGE_MASK) == (tlb_addr &amp;amp; (TARGET_PAGE_MASK | TLB_INVALID_MASK))) {&lt;br /&gt;      physaddr = addr + env-&gt;tlb_table[mmu_idx][index].addend;&lt;br /&gt;      if (tlb_addr &amp;amp; ~TARGET_PAGE_MASK) {&lt;br /&gt;          /* IO access */&lt;br /&gt;          if ((addr &amp;amp; (DATA_SIZE - 1)) != 0)&lt;br /&gt;              goto do_unaligned_access;&lt;br /&gt;          retaddr = GETPC();&lt;br /&gt;          glue(io_write, SUFFIX)(physaddr, val, tlb_addr, retaddr);&lt;br /&gt;      } else if (((addr &amp;amp; ~TARGET_PAGE_MASK) + DATA_SIZE - 1) &gt;= TARGET_PAGE_SIZE) {&lt;br /&gt;      do_unaligned_access:&lt;br /&gt;          retaddr = GETPC();&lt;br /&gt;#ifdef ALIGNED_ONLY&lt;br /&gt;          do_unaligned_access(addr, 1, mmu_idx, retaddr);&lt;br /&gt;#endif&lt;br /&gt;          glue(glue(slow_st, SUFFIX), MMUSUFFIX)(addr, val,&lt;br /&gt;                                                 mmu_idx, retaddr);&lt;br /&gt;      } else {&lt;br /&gt;          /* aligned/unaligned access in the same page */&lt;br /&gt;#ifdef ALIGNED_ONLY&lt;br /&gt;          if ((addr &amp;amp; (DATA_SIZE - 1)) != 0) {&lt;br /&gt;              retaddr = GETPC();&lt;br /&gt;              do_unaligned_access(addr, 1, mmu_idx, retaddr);&lt;br /&gt;          }&lt;br /&gt;#endif&lt;br /&gt;          glue(glue(st, SUFFIX), _raw)((uint8_t *)(long)physaddr, val);&lt;br /&gt;      }&lt;br /&gt;  } else {&lt;br /&gt;      /* the page is not in the TLB : fill it */&lt;br /&gt;      retaddr = GETPC();&lt;br /&gt;#ifdef ALIGNED_ONLY&lt;br /&gt;      if ((addr &amp;amp; (DATA_SIZE - 1)) != 0)&lt;br /&gt;          do_unaligned_access(addr, 1, mmu_idx, retaddr);&lt;br /&gt;#endif&lt;br /&gt;      tlb_fill(addr, 1, mmu_idx, retaddr);&lt;br /&gt;      goto redo;&lt;br /&gt;  }&lt;br /&gt;}&lt;/blockquote&gt;static 関数の glue(io_write, SUFFIX)(physaddr, val, tlb_addr, retaddr); が呼ばれて (io_writel(...))、最終的に io_write[][](...) の形で、関数ポインタがコールされる。&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3477330834625238216-4244491187916877365?l=qemumemo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://qemumemo.blogspot.com/feeds/4244491187916877365/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://qemumemo.blogspot.com/2009/01/cpu-io.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3477330834625238216/posts/default/4244491187916877365'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3477330834625238216/posts/default/4244491187916877365'/><link rel='alternate' type='text/html' href='http://qemumemo.blogspot.com/2009/01/cpu-io.html' title='CPU から I/O 空間 （タイマー） へのアクセス'/><author><name>aloha</name><uri>http://www.blogger.com/profile/17250121836567925230</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3477330834625238216.post-8766417990316029613</id><published>2009-01-07T10:22:00.002+09:00</published><updated>2009-01-07T11:07:17.257+09:00</updated><title type='text'>タイマー割り込みが CPU に通知されるまで</title><content type='html'>&lt;div&gt;前回の記事の続き。&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;main_loop_wait (vl.c) の中でイベントの有無がチェックされる。最後に bottom-halves がチェックされる。&lt;div&gt;&lt;blockquote&gt;void main_loop_wait(int timeout)&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;&lt;div&gt;&lt;br /&gt;...&lt;br /&gt;&lt;br /&gt;    /* Check bottom-halves last in case any of the earlier events triggered them.  */&lt;br /&gt;    qemu_bh_poll();&lt;br /&gt;}&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;int qemu_bh_poll(void)&lt;/div&gt;&lt;div&gt;{&lt;/div&gt;&lt;div&gt;    QEMUBH *bh, **pbh;&lt;/div&gt;&lt;div&gt;    int ret;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;    ret = 0;&lt;/div&gt;&lt;div&gt;    for(;;) {&lt;/div&gt;&lt;div&gt;        pbh = &amp;amp;first_bh;&lt;/div&gt;&lt;div&gt;        bh = *pbh;&lt;/div&gt;&lt;div&gt;        if (!bh)&lt;/div&gt;&lt;div&gt;            break;&lt;/div&gt;&lt;div&gt;        ret = 1;&lt;/div&gt;&lt;div&gt;        *pbh = bh-&gt;next;&lt;/div&gt;&lt;div&gt;        bh-&gt;scheduled = 0;&lt;/div&gt;&lt;div&gt;        bh-&gt;cb(bh-&gt;opaque);&lt;/div&gt;&lt;div&gt;    }&lt;/div&gt;&lt;div&gt;    return ret;&lt;/div&gt;&lt;div&gt;}&lt;/div&gt;&lt;/div&gt;&lt;/blockquote&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;bh-&gt;cb(bh-&gt;opaque)  から sp804 という arm のタイマーモジュール (hw/arm_timer.c) に入っていく。cb は QEMUBHFunc * 型 (qemu-common.h:typedef void QEMUBHFunc(void *opaque);) の関数ポインタで、arm_timer_tick() が入ってる。opaque には arm_timer_state * が入ってる。&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;blockquote&gt;&lt;div&gt;static void arm_timer_tick(void *opaque)&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;{&lt;/div&gt;&lt;div&gt;    arm_timer_state *s = (arm_timer_state *)opaque;&lt;/div&gt;&lt;div&gt;    s-&gt;int_level = 1;&lt;/div&gt;&lt;div&gt;    arm_timer_update(s);&lt;/div&gt;&lt;div&gt;}&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;typedef struct {&lt;/div&gt;&lt;div&gt;    ptimer_state *timer;&lt;/div&gt;&lt;div&gt;    uint32_t control;&lt;/div&gt;&lt;div&gt;    uint32_t limit;&lt;/div&gt;&lt;div&gt;    int freq;&lt;/div&gt;&lt;div&gt;    int int_level;&lt;/div&gt;&lt;div&gt;    qemu_irq irq;&lt;/div&gt;&lt;div&gt;} arm_timer_state;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;/* Check all active timers, and schedule the next timer interrupt.  */&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;static void arm_timer_update(arm_timer_state *s)&lt;/div&gt;&lt;div&gt;{&lt;/div&gt;&lt;div&gt;    /* Update interrupts.  */&lt;/div&gt;&lt;div&gt;    if (s-&gt;int_level &amp;amp;&amp;amp; (s-&gt;control &amp;amp; TIMER_CTRL_IE)) {&lt;/div&gt;&lt;div&gt;        qemu_irq_raise(s-&gt;irq);&lt;/div&gt;&lt;div&gt;    } else {&lt;/div&gt;&lt;div&gt;        qemu_irq_lower(s-&gt;irq);&lt;/div&gt;&lt;div&gt;    }&lt;/div&gt;&lt;div&gt;}&lt;/div&gt;&lt;/blockquote&gt;&lt;/div&gt;qemu_irq_raise は qemu_set_irq(irq, 1)。そして irq-&gt;handler(irq-&gt;opaque, irq-&gt;n, 1) となる。&lt;div&gt;handler には sp804_set_irq() 、opaque には sp804_state が入ってる。&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;blockquote&gt;&lt;div&gt;typedef struct {&lt;/div&gt;&lt;div&gt;    void *timer[2];&lt;/div&gt;&lt;div&gt;    int level[2];&lt;/div&gt;&lt;div&gt;    uint32_t base;&lt;/div&gt;&lt;div&gt;    qemu_irq irq;&lt;/div&gt;&lt;div&gt;} sp804_state;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;/* Merge the IRQs from the two component devices.  */&lt;/div&gt;&lt;div&gt;static void sp804_set_irq(void *opaque, int irq, int level)&lt;/div&gt;&lt;div&gt;{&lt;/div&gt;&lt;div&gt;    sp804_state *s = (sp804_state *)opaque;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;    s-&gt;level[irq] = level;&lt;/div&gt;&lt;div&gt;    qemu_set_irq(s-&gt;irq, s-&gt;level[0] || s-&gt;level[1]);&lt;/div&gt;&lt;div&gt;}&lt;/div&gt;&lt;/blockquote&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;そしてまた qemu_set_irq から handler が呼び出されるという流れで、ARM の GIC (Generic Interrupt Controller) の gic_set_irq (arm_gic.c) が呼び出される。&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;blockquote&gt;&lt;div&gt;/* Process a change in an external IRQ input.  */&lt;/div&gt;&lt;div&gt;static void gic_set_irq(void *opaque, int irq, int level)&lt;/div&gt;&lt;div&gt;{&lt;/div&gt;&lt;div&gt;    gic_state *s = (gic_state *)opaque;&lt;/div&gt;&lt;div&gt;    /* The first external input line is internal interrupt 32.  */&lt;/div&gt;&lt;div&gt;    irq += 32;&lt;/div&gt;&lt;div&gt;    if (level == GIC_TEST_LEVEL(irq, ALL_CPU_MASK))&lt;/div&gt;&lt;div&gt;        return;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;    if (level) {&lt;/div&gt;&lt;div&gt;        GIC_SET_LEVEL(irq, ALL_CPU_MASK);&lt;/div&gt;&lt;div&gt;        if (GIC_TEST_TRIGGER(irq) || GIC_TEST_ENABLED(irq)) {&lt;/div&gt;&lt;div&gt;            DPRINTF("Set %d pending mask %x\n", irq, GIC_TARGET(irq));&lt;/div&gt;&lt;div&gt;            GIC_SET_PENDING(irq, GIC_TARGET(irq));&lt;/div&gt;&lt;div&gt;        }&lt;/div&gt;&lt;div&gt;    } else {&lt;/div&gt;&lt;div&gt;        GIC_CLEAR_LEVEL(irq, ALL_CPU_MASK);&lt;/div&gt;&lt;div&gt;    }&lt;/div&gt;&lt;div&gt;    gic_update(s);&lt;/div&gt;&lt;div&gt;}&lt;/div&gt;&lt;/blockquote&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;ここで GIC_SET_PENDING で gic_state を変化させて gic_update() に行く。&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;blockquote&gt;&lt;div&gt;/* TODO: Many places that call this routine could be optimized.  */&lt;/div&gt;&lt;div&gt;/* Update interrupt status after enabled or pending bits have been changed.  */&lt;/div&gt;&lt;div&gt;static void gic_update(gic_state *s)&lt;/div&gt;&lt;div&gt;{&lt;/div&gt;&lt;div&gt;    int best_irq;&lt;/div&gt;&lt;div&gt;    int best_prio;&lt;/div&gt;&lt;div&gt;    int irq;&lt;/div&gt;&lt;div&gt;    int level;&lt;/div&gt;&lt;div&gt;    int cpu;&lt;/div&gt;&lt;div&gt;    int cm;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;    for (cpu = 0; cpu &lt;&gt;&lt;div&gt;        cm = 1 &lt;&lt;&gt;&lt;div&gt;        s-&gt;current_pending[cpu] = 1023;&lt;/div&gt;&lt;div&gt;        if (!s-&gt;enabled || !s-&gt;cpu_enabled[cpu]) {&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;    qemu_irq_lower(s-&gt;parent_irq[cpu]);&lt;/div&gt;&lt;div&gt;            return;&lt;/div&gt;&lt;div&gt;        }&lt;/div&gt;&lt;div&gt;        best_prio = 0x100;&lt;/div&gt;&lt;div&gt;        best_irq = 1023;&lt;/div&gt;&lt;div&gt;        for (irq = 0; irq &lt;&gt;&lt;div&gt;            if (GIC_TEST_ENABLED(irq) &amp;amp;&amp;amp; GIC_TEST_PENDING(irq, cm)) {&lt;/div&gt;&lt;div&gt;                if (GIC_GET_PRIORITY(irq, cpu) &lt;&gt;&lt;div&gt;                    best_prio = GIC_GET_PRIORITY(irq, cpu);&lt;/div&gt;&lt;div&gt;                    best_irq = irq;&lt;/div&gt;&lt;div&gt;                }&lt;/div&gt;&lt;div&gt;            }&lt;/div&gt;&lt;div&gt;        }&lt;/div&gt;&lt;div&gt;        level = 0;&lt;/div&gt;&lt;div&gt;        if (best_prio &lt;= s-&gt;priority_mask[cpu]) {&lt;/div&gt;&lt;div&gt;            s-&gt;current_pending[cpu] = best_irq;&lt;/div&gt;&lt;div&gt;            if (best_prio &lt;&gt;running_priority[cpu]) {&lt;/div&gt;&lt;div&gt;                DPRINTF("Raised pending IRQ %d\n", best_irq);&lt;/div&gt;&lt;div&gt;                level = 1;&lt;/div&gt;&lt;div&gt;            }&lt;/div&gt;&lt;div&gt;        }&lt;/div&gt;&lt;div&gt;        qemu_set_irq(s-&gt;parent_irq[cpu], level);&lt;/div&gt;&lt;div&gt;    }&lt;/div&gt;&lt;div&gt;}&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/blockquote&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;qemu_set_irq(s-&gt;parent_irq[cpu], level); から、parent_irq[0] (CPU 1 つの場合) のハンドラを呼び出して、arm_pic_cpu_handler に行く。opaque は CPUState (ARMCPUState) で、これが最後。&lt;/div&gt;&lt;div&gt;最終的に cpu_interrupt(env, CPU_INTERRUPT_HARD) が呼ばれて、タイマー割り込みが CPU に通知される。&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;そして再び main_loop で cpu_exec(env) を実行して、その中で割り込み pending が入ってるから longjump で巻き戻して、という流れで割り込みを処理する。&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3477330834625238216-8766417990316029613?l=qemumemo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://qemumemo.blogspot.com/feeds/8766417990316029613/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://qemumemo.blogspot.com/2009/01/cpu.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3477330834625238216/posts/default/8766417990316029613'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3477330834625238216/posts/default/8766417990316029613'/><link rel='alternate' type='text/html' href='http://qemumemo.blogspot.com/2009/01/cpu.html' title='タイマー割り込みが CPU に通知されるまで'/><author><name>aloha</name><uri>http://www.blogger.com/profile/17250121836567925230</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3477330834625238216.post-5743035945145336293</id><published>2009-01-05T11:35:00.003+09:00</published><updated>2009-01-05T12:04:24.510+09:00</updated><title type='text'>main_loop</title><content type='html'>QEMU の基本構造は (vl.c)&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;int main() {&lt;/div&gt;&lt;div&gt;   オプション解析や初期化など。&lt;/div&gt;&lt;div&gt;   main_loop();&lt;/div&gt;&lt;div&gt;}&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;main_loop() {&lt;/div&gt;&lt;div&gt;  for(;;) {&lt;/div&gt;&lt;div&gt;    if(実行中) {&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;      for(;;) {&lt;/div&gt;&lt;div&gt;        ret = cpu_exec(); /* Basic Block 実行 */&lt;/div&gt;&lt;div&gt;        if(割り込みがあった) {&lt;/div&gt;&lt;div&gt;           ret = EXCP_INTERRUPT;&lt;/div&gt;&lt;div&gt;           break;&lt;/div&gt;&lt;div&gt;        }&lt;/div&gt;&lt;div&gt;     }&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;      if(ret == EXCP_HALTED)&lt;/div&gt;&lt;div&gt;        timeout = 10;&lt;/div&gt;&lt;div&gt;      else&lt;/div&gt;&lt;div&gt;         timeout = 0;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;      main_loop_wait(timeout);&lt;/div&gt;&lt;div&gt;    }&lt;/div&gt;&lt;div&gt;  }&lt;/div&gt;&lt;div&gt;}&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;らしい。基本ブロックを実行して main_loop_wait() して、の繰り返し。&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;cpu_exec(env) {&lt;/div&gt;&lt;div&gt;&lt;div&gt;  if(BB キャッシュあり) {&lt;/div&gt;&lt;div&gt;    そのまま実行 （機械語列に制御を渡す）&lt;/div&gt;&lt;div&gt;  } else {&lt;/div&gt;&lt;div&gt;    BB を JIT して、キャッシュしておく。&lt;/div&gt;&lt;div&gt;  }&lt;/div&gt;&lt;div&gt;}&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;main_loop_wait() {&lt;/div&gt;&lt;div&gt;&lt;div&gt;    &lt;/div&gt;&lt;div&gt;  /* XXX: need to suppress polling by better using win32 events */&lt;/div&gt;&lt;div&gt;  ret = 0;&lt;/div&gt;&lt;div&gt;  for(pe = first_polling_entry; pe != NULL; pe = pe-&gt;next) {&lt;/div&gt;&lt;div&gt;      ret |= pe-&gt;func(pe-&gt;opaque);&lt;/div&gt;&lt;div&gt;  }&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;#ifdef _WIN32&lt;/div&gt;&lt;div&gt;  if(ret == 0) {&lt;/div&gt;&lt;div&gt;    ret = WaitForMultipleObjects(....., timeout);&lt;/div&gt;&lt;div&gt;#endif&lt;/div&gt;&lt;div&gt;}&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;timeout が 0 の場合、条件を調べて即制御を返す。&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3477330834625238216-5743035945145336293?l=qemumemo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://qemumemo.blogspot.com/feeds/5743035945145336293/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://qemumemo.blogspot.com/2009/01/mainloop.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3477330834625238216/posts/default/5743035945145336293'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3477330834625238216/posts/default/5743035945145336293'/><link rel='alternate' type='text/html' href='http://qemumemo.blogspot.com/2009/01/mainloop.html' title='main_loop'/><author><name>aloha</name><uri>http://www.blogger.com/profile/17250121836567925230</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3477330834625238216.post-7471880620808949028</id><published>2009-01-05T11:06:00.001+09:00</published><updated>2009-01-05T11:08:18.268+09:00</updated><title type='text'>xen-ioemu</title><content type='html'>xen は ioemu という、qemu のコードを利用した機能で io 操作のエミュレートを実現しているらしい。&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;a href="http://www.itmedia.co.jp/enterprise/articles/0701/12/news010.html"&gt;http://www.itmedia.co.jp/enterprise/articles/0701/12/news010.html&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3477330834625238216-7471880620808949028?l=qemumemo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://qemumemo.blogspot.com/feeds/7471880620808949028/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://qemumemo.blogspot.com/2009/01/xen-ioemu.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3477330834625238216/posts/default/7471880620808949028'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3477330834625238216/posts/default/7471880620808949028'/><link rel='alternate' type='text/html' href='http://qemumemo.blogspot.com/2009/01/xen-ioemu.html' title='xen-ioemu'/><author><name>aloha</name><uri>http://www.blogger.com/profile/17250121836567925230</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3477330834625238216.post-6793067847238391262</id><published>2008-12-24T10:14:00.003+09:00</published><updated>2008-12-24T10:57:31.714+09:00</updated><title type='text'>Memory Map の作り方</title><content type='html'>CPUReadMemoryFun *&lt;span class="Apple-style-span" style="font-style: italic;"&gt;foo_readfn&lt;/span&gt;[3]  と CPUWriteMemoryFunc *&lt;span class="Apple-style-span" style="font-style: italic;"&gt;foo_writef&lt;/span&gt;n[3]  をそれぞれ定義する。配列の中身は、それぞれ、メモリを byte/word/double word で読んだときに呼び出されるコールバック。&lt;div&gt;&lt;blockquote&gt;iomemtype = cpu_register_io_memory(io_index, &lt;span class="Apple-style-span" style="font-style: italic;"&gt;foo_readfn&lt;/span&gt;,&lt;span class="Apple-style-span" style="font-style: italic;"&gt;foo_writefn&lt;/span&gt;, s);&lt;br /&gt;cpu_register_physical_memory(開始アドレス, サイズ, iomemtype);&lt;/blockquote&gt;&lt;div&gt;io_index が 0 の時は新しい io 領域が作られる。&lt;/div&gt;&lt;div&gt;s は、CPU の io の状態を表現する任意の構造体。&lt;/div&gt;&lt;div&gt;サイズはターゲットのページサイズの倍数。&lt;/div&gt;&lt;div&gt;iomemtype (phys_offset) は、phys_offset &amp;amp; ~TARGET_PAGE_MASK) != 0 となる ( io memory page)。&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;qemu-0.9.1/exec.c&lt;br /&gt;&lt;blockquote&gt;&lt;span style="font-family:monospace;"&gt;&lt;br /&gt;&lt;span style="color:#0000ff;"&gt;/*&lt;/span&gt;&lt;span style="color:#0000ff;"&gt; mem_read and mem_write are arrays of functions containing the&lt;/span&gt;&lt;br /&gt;&lt;span style="color:#0000ff;"&gt;   function to access byte (index &lt;/span&gt;&lt;span style="background-;color:#f2f2f2;"&gt;&lt;span style="color:#ff00ff;"&gt;0&lt;/span&gt;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;), word (index &lt;/span&gt;&lt;span style="background-;color:#f2f2f2;"&gt;&lt;span style="color:#ff00ff;"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;) and dword (index&lt;/span&gt;&lt;br /&gt;&lt;span style="color:#0000ff;"&gt;   &lt;/span&gt;&lt;span style="background-;color:#f2f2f2;"&gt;&lt;span style="color:#ff00ff;"&gt;2&lt;/span&gt;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;). Functions can be omitted with a NULL function pointer. The&lt;/span&gt;&lt;br /&gt;&lt;span style="color:#0000ff;"&gt;   registered functions may be modified dynamically later.&lt;/span&gt;&lt;br /&gt;&lt;span style="color:#0000ff;"&gt;   If io_index is non zero, the corresponding io zone is&lt;/span&gt;&lt;br /&gt;&lt;span style="color:#0000ff;"&gt;   modified. If it is zero, a new io zone is allocated. The return&lt;/span&gt;&lt;br /&gt;&lt;span style="color:#0000ff;"&gt;   value can be used with cpu_register_physical_memory(). (-&lt;/span&gt;&lt;span style="background-;color:#f2f2f2;"&gt;&lt;span style="color:#ff00ff;"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;) is&lt;/span&gt;&lt;br /&gt;&lt;span style="color:#0000ff;"&gt;   returned if error. &lt;/span&gt;&lt;span style="color:#0000ff;"&gt;*/&lt;/span&gt;&lt;br /&gt;&lt;span style="color:#2e8b57;"&gt;&lt;b&gt;int&lt;/b&gt;&lt;/span&gt; cpu_register_io_memory(&lt;span style="color:#2e8b57;"&gt;&lt;b&gt;int&lt;/b&gt;&lt;/span&gt; io_index,&lt;br /&gt;                           CPUReadMemoryFunc **mem_read,&lt;br /&gt;                           CPUWriteMemoryFunc **mem_write,&lt;br /&gt;                           &lt;span style="color:#2e8b57;"&gt;&lt;b&gt;void&lt;/b&gt;&lt;/span&gt; *opaque)&lt;br /&gt;{&lt;br /&gt;    &lt;span style="color:#2e8b57;"&gt;&lt;b&gt;int&lt;/b&gt;&lt;/span&gt; i, subwidth = &lt;span style="background-;color:#f2f2f2;"&gt;&lt;span style="color:#ff00ff;"&gt;0&lt;/span&gt;&lt;/span&gt;;&lt;br /&gt;&lt;br /&gt;    &lt;span style="color:#804040;"&gt;&lt;b&gt;if&lt;/b&gt;&lt;/span&gt; (io_index &amp;lt;= &lt;span style="background-;color:#f2f2f2;"&gt;&lt;span style="color:#ff00ff;"&gt;0&lt;/span&gt;&lt;/span&gt;) {&lt;br /&gt;        &lt;span style="color:#804040;"&gt;&lt;b&gt;if&lt;/b&gt;&lt;/span&gt; (io_mem_nb &amp;gt;= IO_MEM_NB_ENTRIES)&lt;br /&gt;            &lt;span style="color:#804040;"&gt;&lt;b&gt;return&lt;/b&gt;&lt;/span&gt; -&lt;span style="background-;color:#f2f2f2;"&gt;&lt;span style="color:#ff00ff;"&gt;1&lt;/span&gt;&lt;/span&gt;;&lt;br /&gt;        io_index = io_mem_nb++;&lt;br /&gt;    } &lt;span style="color:#804040;"&gt;&lt;b&gt;else&lt;/b&gt;&lt;/span&gt; {&lt;br /&gt;        &lt;span style="color:#804040;"&gt;&lt;b&gt;if&lt;/b&gt;&lt;/span&gt; (io_index &amp;gt;= IO_MEM_NB_ENTRIES)&lt;br /&gt;            &lt;span style="color:#804040;"&gt;&lt;b&gt;return&lt;/b&gt;&lt;/span&gt; -&lt;span style="background-;color:#f2f2f2;"&gt;&lt;span style="color:#ff00ff;"&gt;1&lt;/span&gt;&lt;/span&gt;;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    &lt;span style="color:#804040;"&gt;&lt;b&gt;for&lt;/b&gt;&lt;/span&gt;(i = &lt;span style="background-;color:#f2f2f2;"&gt;&lt;span style="color:#ff00ff;"&gt;0&lt;/span&gt;&lt;/span&gt;;i &amp;lt; &lt;span style="background-;color:#f2f2f2;"&gt;&lt;span style="color:#ff00ff;"&gt;3&lt;/span&gt;&lt;/span&gt;; i++) {&lt;br /&gt;        &lt;span style="color:#804040;"&gt;&lt;b&gt;if&lt;/b&gt;&lt;/span&gt; (!mem_read[i] || !mem_write[i])&lt;br /&gt;            subwidth = IO_MEM_SUBWIDTH;&lt;br /&gt;        io_mem_read[io_index][i] = mem_read[i];&lt;br /&gt;        io_mem_write[io_index][i] = mem_write[i];&lt;br /&gt;    }&lt;br /&gt;    io_mem_opaque[io_index] = opaque;&lt;br /&gt;    &lt;span style="color:#804040;"&gt;&lt;b&gt;return&lt;/b&gt;&lt;/span&gt; (io_index &amp;lt;&amp;lt; IO_MEM_SHIFT) | subwidth;&lt;br /&gt;}&lt;br /&gt;&lt;/span&gt;&lt;/blockquote&gt;&lt;br /&gt;qemu-0.9.1/cpu-all.h&lt;br /&gt;&lt;span style="font-family:monospace;"&gt;&lt;span style="color:#2e8b57;"&gt;&lt;b&gt;&lt;/b&gt;&lt;/span&gt;&lt;blockquote&gt;&lt;span style="color:#2e8b57;"&gt;&lt;b&gt;typedef&lt;/b&gt;&lt;/span&gt; &lt;span style="color:#2e8b57;"&gt;&lt;b&gt;void&lt;/b&gt;&lt;/span&gt; CPUWriteMemoryFunc(&lt;span style="color:#2e8b57;"&gt;&lt;b&gt;void&lt;/b&gt;&lt;/span&gt; *opaque,&lt;br /&gt;                                target_phys_addr_t addr,&lt;br /&gt;                                &lt;span style="color:#2e8b57;"&gt;&lt;b&gt;uint32_t&lt;/b&gt;&lt;/span&gt; value);&lt;br /&gt;&lt;br /&gt;&lt;span style="color:#2e8b57;"&gt;&lt;b&gt;typedef&lt;/b&gt;&lt;/span&gt; &lt;span style="color:#2e8b57;"&gt;&lt;b&gt;uint32_t&lt;/b&gt;&lt;/span&gt; CPUReadMemoryFunc(&lt;span style="color:#2e8b57;"&gt;&lt;b&gt;void&lt;/b&gt;&lt;/span&gt; *opaque,&lt;br /&gt;                                   target_phys_addr_t addr);&lt;br /&gt;&lt;br /&gt;&lt;span style="color:#2e8b57;"&gt;&lt;b&gt;int&lt;/b&gt;&lt;/span&gt; cpu_register_io_memory(&lt;span style="color:#2e8b57;"&gt;&lt;b&gt;int&lt;/b&gt;&lt;/span&gt; io_index,&lt;br /&gt;                           CPUReadMemoryFunc **mem_read,&lt;br /&gt;                           CPUWriteMemoryFunc **mem_write,&lt;br /&gt;                           &lt;span style="color:#2e8b57;"&gt;&lt;b&gt;void&lt;/b&gt;&lt;/span&gt; *opaque);&lt;/blockquote&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3477330834625238216-6793067847238391262?l=qemumemo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://qemumemo.blogspot.com/feeds/6793067847238391262/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://qemumemo.blogspot.com/2008/12/memory-map.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3477330834625238216/posts/default/6793067847238391262'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3477330834625238216/posts/default/6793067847238391262'/><link rel='alternate' type='text/html' href='http://qemumemo.blogspot.com/2008/12/memory-map.html' title='Memory Map の作り方'/><author><name>aloha</name><uri>http://www.blogger.com/profile/17250121836567925230</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3477330834625238216.post-2641063346840027657</id><published>2008-12-23T12:55:00.004+09:00</published><updated>2008-12-23T13:13:00.349+09:00</updated><title type='text'>QEMU で新しい target board を作るためには</title><content type='html'>&lt;div&gt;詳しい追加場所や、QEMU の API などは、qemu-0.9.1/hw/integratorcp.[co] などを参考に。&lt;/div&gt;&lt;ol&gt;&lt;li&gt;qemu-0.9.1/hw/board.h に extern QEMUMachine  &lt;span style="font-style:italic;"&gt;sample_machine&lt;/span&gt;;  を追加する。&lt;br /&gt;&lt;/li&gt;&lt;li&gt;qemu-0.9.1/hw/&lt;span class="Apple-style-span" style="font-style: italic;"&gt;sample_board&lt;/span&gt;.c の中で、board.h に追加した exterm 宣言の実体を定義する。具体的には、ターゲットボードの初期化関数 &lt;span class="Apple-style-span" style="font-style: italic;"&gt;sample_board_init&lt;/span&gt;() などを定義し、QEMUMachine &lt;span class="Apple-style-span" style="font-style: italic;"&gt;sample_machine&lt;/span&gt; = {"&lt;span class="Apple-style-span" style="font-style: italic;"&gt;sampleboard&lt;/span&gt;", "説明", &lt;span class="Apple-style-span" style="font-style: italic;"&gt;sample_board_init&lt;/span&gt;}; &lt;/li&gt;&lt;li&gt;qemu-0.9.1/Makefile.target に &lt;span class="Apple-style-span" style="font-style: italic;"&gt;sample_board&lt;/span&gt;.o を追加する。これで &lt;span class="Apple-style-span" style="font-style: italic;"&gt;sample_board&lt;/span&gt;.c がビルドされてリンクされる。&lt;/li&gt;&lt;li&gt;qemu-0.9.1/vl.c に qemu_register_machine(&amp;amp;&lt;span class="Apple-style-span" style="font-style: italic;"&gt;sample_machine&lt;/span&gt;); を追加する。これで、QEMU の引数に -M &lt;span class="Apple-style-span" style="font-style: italic;"&gt;sampleboard&lt;/span&gt; を渡したときに、ターゲットボードの初期化と実行が行われるようになる。&lt;/li&gt;&lt;/ol&gt;&lt;div&gt;あとは &lt;span class="Apple-style-span" style="font-style: italic;"&gt;sample_board&lt;/span&gt;.c の中でひたすらボードの定義 （メモリマップなど） と初期化を書けば良い。&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3477330834625238216-2641063346840027657?l=qemumemo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://qemumemo.blogspot.com/feeds/2641063346840027657/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://qemumemo.blogspot.com/2008/12/blog-post.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3477330834625238216/posts/default/2641063346840027657'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3477330834625238216/posts/default/2641063346840027657'/><link rel='alternate' type='text/html' href='http://qemumemo.blogspot.com/2008/12/blog-post.html' title='QEMU で新しい target board を作るためには'/><author><name>aloha</name><uri>http://www.blogger.com/profile/17250121836567925230</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3477330834625238216.post-58334294560749727</id><published>2008-12-22T18:58:00.002+09:00</published><updated>2008-12-22T19:02:42.277+09:00</updated><title type='text'>CPUState</title><content type='html'>けっこう探すのに難儀した。実体は qemu-0.9.1/target-arm など。CPU は、一応ちゃんとターゲットごとに分かれている。ボードもちゃんと分けて欲しい。&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;font face="monospace"&gt;&lt;br /&gt;&lt;font color="#0000ff"&gt;/*&lt;/font&gt;&lt;font color="#0000ff"&gt;&amp;nbsp;We currently assume float and double are IEEE single and double&lt;/font&gt;&lt;br /&gt;&lt;font color="#0000ff"&gt;&amp;nbsp;&amp;nbsp; precision respectively.&lt;/font&gt;&lt;br /&gt;&lt;font color="#0000ff"&gt;&amp;nbsp;&amp;nbsp; Doing runtime conversions is tricky because VFP registers may contain&lt;/font&gt;&lt;br /&gt;&lt;font color="#0000ff"&gt;&amp;nbsp;&amp;nbsp; integer values (eg. as the result of a FTOSI instruction).&lt;/font&gt;&lt;br /&gt;&lt;font color="#0000ff"&gt;&amp;nbsp;&amp;nbsp; s&amp;lt;2n&amp;gt; maps to the least significant half of d&amp;lt;n&amp;gt;&lt;/font&gt;&lt;br /&gt;&lt;font color="#0000ff"&gt;&amp;nbsp;&amp;nbsp; s&amp;lt;2n+&lt;/font&gt;&lt;span style="background-color: #f2f2f2"&gt;&lt;font color="#ff00ff"&gt;1&lt;/font&gt;&lt;/span&gt;&lt;font color="#0000ff"&gt;&amp;gt; maps to the most significant half of d&amp;lt;n&amp;gt;&lt;/font&gt;&lt;br /&gt;&lt;font color="#0000ff"&gt;&amp;nbsp;&lt;/font&gt;&lt;font color="#0000ff"&gt;*/&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;font color="#2e8b57"&gt;&lt;b&gt;typedef&lt;/b&gt;&lt;/font&gt;&amp;nbsp;&lt;font color="#2e8b57"&gt;&lt;b&gt;struct&lt;/b&gt;&lt;/font&gt;&amp;nbsp;CPUARMState {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#0000ff"&gt;/*&lt;/font&gt;&lt;font color="#0000ff"&gt;&amp;nbsp;Regs for current mode.&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color="#0000ff"&gt;*/&lt;/font&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#2e8b57"&gt;&lt;b&gt;uint32_t&lt;/b&gt;&lt;/font&gt;&amp;nbsp;regs[&lt;span style="background-color: #f2f2f2"&gt;&lt;font color="#ff00ff"&gt;16&lt;/font&gt;&lt;/span&gt;];&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#0000ff"&gt;/*&lt;/font&gt;&lt;font color="#0000ff"&gt;&amp;nbsp;Frequently accessed CPSR bits are stored separately for efficiently.&lt;/font&gt;&lt;br /&gt;&lt;font color="#0000ff"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; This contains all the other bits.&amp;nbsp;&amp;nbsp;Use cpsr_{read,write} to access&lt;/font&gt;&lt;br /&gt;&lt;font color="#0000ff"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; the whole CPSR.&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color="#0000ff"&gt;*/&lt;/font&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#2e8b57"&gt;&lt;b&gt;uint32_t&lt;/b&gt;&lt;/font&gt;&amp;nbsp;uncached_cpsr;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#2e8b57"&gt;&lt;b&gt;uint32_t&lt;/b&gt;&lt;/font&gt;&amp;nbsp;spsr;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#0000ff"&gt;/*&lt;/font&gt;&lt;font color="#0000ff"&gt;&amp;nbsp;Banked registers.&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color="#0000ff"&gt;*/&lt;/font&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#2e8b57"&gt;&lt;b&gt;uint32_t&lt;/b&gt;&lt;/font&gt;&amp;nbsp;banked_spsr[&lt;span style="background-color: #f2f2f2"&gt;&lt;font color="#ff00ff"&gt;6&lt;/font&gt;&lt;/span&gt;];&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#2e8b57"&gt;&lt;b&gt;uint32_t&lt;/b&gt;&lt;/font&gt;&amp;nbsp;banked_r13[&lt;span style="background-color: #f2f2f2"&gt;&lt;font color="#ff00ff"&gt;6&lt;/font&gt;&lt;/span&gt;];&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#2e8b57"&gt;&lt;b&gt;uint32_t&lt;/b&gt;&lt;/font&gt;&amp;nbsp;banked_r14[&lt;span style="background-color: #f2f2f2"&gt;&lt;font color="#ff00ff"&gt;6&lt;/font&gt;&lt;/span&gt;];&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#0000ff"&gt;/*&lt;/font&gt;&lt;font color="#0000ff"&gt;&amp;nbsp;These hold r8-r12.&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color="#0000ff"&gt;*/&lt;/font&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#2e8b57"&gt;&lt;b&gt;uint32_t&lt;/b&gt;&lt;/font&gt;&amp;nbsp;usr_regs[&lt;span style="background-color: #f2f2f2"&gt;&lt;font color="#ff00ff"&gt;5&lt;/font&gt;&lt;/span&gt;];&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#2e8b57"&gt;&lt;b&gt;uint32_t&lt;/b&gt;&lt;/font&gt;&amp;nbsp;fiq_regs[&lt;span style="background-color: #f2f2f2"&gt;&lt;font color="#ff00ff"&gt;5&lt;/font&gt;&lt;/span&gt;];&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#0000ff"&gt;/*&lt;/font&gt;&lt;font color="#0000ff"&gt;&amp;nbsp;cpsr flag cache for faster execution &lt;/font&gt;&lt;font color="#0000ff"&gt;*/&lt;/font&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#2e8b57"&gt;&lt;b&gt;uint32_t&lt;/b&gt;&lt;/font&gt;&amp;nbsp;CF; &lt;font color="#0000ff"&gt;/*&lt;/font&gt;&lt;font color="#0000ff"&gt;&amp;nbsp;&lt;/font&gt;&lt;span style="background-color: #f2f2f2"&gt;&lt;font color="#ff00ff"&gt;0&lt;/font&gt;&lt;/span&gt;&lt;font color="#0000ff"&gt;&amp;nbsp;or &lt;/font&gt;&lt;span style="background-color: #f2f2f2"&gt;&lt;font color="#ff00ff"&gt;1&lt;/font&gt;&lt;/span&gt;&lt;font color="#0000ff"&gt;&amp;nbsp;&lt;/font&gt;&lt;font color="#0000ff"&gt;*/&lt;/font&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#2e8b57"&gt;&lt;b&gt;uint32_t&lt;/b&gt;&lt;/font&gt;&amp;nbsp;VF; &lt;font color="#0000ff"&gt;/*&lt;/font&gt;&lt;font color="#0000ff"&gt;&amp;nbsp;V is the bit &lt;/font&gt;&lt;span style="background-color: #f2f2f2"&gt;&lt;font color="#ff00ff"&gt;31.&lt;/font&gt;&lt;/span&gt;&lt;font color="#0000ff"&gt;&amp;nbsp;All other bits are undefined &lt;/font&gt;&lt;font color="#0000ff"&gt;*/&lt;/font&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#2e8b57"&gt;&lt;b&gt;uint32_t&lt;/b&gt;&lt;/font&gt;&amp;nbsp;NZF; &lt;font color="#0000ff"&gt;/*&lt;/font&gt;&lt;font color="#0000ff"&gt;&amp;nbsp;N is bit &lt;/font&gt;&lt;span style="background-color: #f2f2f2"&gt;&lt;font color="#ff00ff"&gt;31.&lt;/font&gt;&lt;/span&gt;&lt;font color="#0000ff"&gt;&amp;nbsp;Z is computed from NZF &lt;/font&gt;&lt;font color="#0000ff"&gt;*/&lt;/font&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#2e8b57"&gt;&lt;b&gt;uint32_t&lt;/b&gt;&lt;/font&gt;&amp;nbsp;QF; &lt;font color="#0000ff"&gt;/*&lt;/font&gt;&lt;font color="#0000ff"&gt;&amp;nbsp;&lt;/font&gt;&lt;span style="background-color: #f2f2f2"&gt;&lt;font color="#ff00ff"&gt;0&lt;/font&gt;&lt;/span&gt;&lt;font color="#0000ff"&gt;&amp;nbsp;or &lt;/font&gt;&lt;span style="background-color: #f2f2f2"&gt;&lt;font color="#ff00ff"&gt;1&lt;/font&gt;&lt;/span&gt;&lt;font color="#0000ff"&gt;&amp;nbsp;&lt;/font&gt;&lt;font color="#0000ff"&gt;*/&lt;/font&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#2e8b57"&gt;&lt;b&gt;uint32_t&lt;/b&gt;&lt;/font&gt;&amp;nbsp;GE; &lt;font color="#0000ff"&gt;/*&lt;/font&gt;&lt;font color="#0000ff"&gt;&amp;nbsp;cpsr[&lt;/font&gt;&lt;span style="background-color: #f2f2f2"&gt;&lt;font color="#ff00ff"&gt;19&lt;/font&gt;&lt;/span&gt;&lt;font color="#0000ff"&gt;:&lt;/font&gt;&lt;span style="background-color: #f2f2f2"&gt;&lt;font color="#ff00ff"&gt;16&lt;/font&gt;&lt;/span&gt;&lt;font color="#0000ff"&gt;] &lt;/font&gt;&lt;font color="#0000ff"&gt;*/&lt;/font&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#2e8b57"&gt;&lt;b&gt;int&lt;/b&gt;&lt;/font&gt;&amp;nbsp;thumb; &lt;font color="#0000ff"&gt;/*&lt;/font&gt;&lt;font color="#0000ff"&gt;&amp;nbsp;cprs[&lt;/font&gt;&lt;span style="background-color: #f2f2f2"&gt;&lt;font color="#ff00ff"&gt;5&lt;/font&gt;&lt;/span&gt;&lt;font color="#0000ff"&gt;]. &lt;/font&gt;&lt;span style="background-color: #f2f2f2"&gt;&lt;font color="#ff00ff"&gt;0&lt;/font&gt;&lt;/span&gt;&lt;font color="#0000ff"&gt;&amp;nbsp;= arm mode, &lt;/font&gt;&lt;span style="background-color: #f2f2f2"&gt;&lt;font color="#ff00ff"&gt;1&lt;/font&gt;&lt;/span&gt;&lt;font color="#0000ff"&gt;&amp;nbsp;= thumb mode. &lt;/font&gt;&lt;font color="#0000ff"&gt;*/&lt;/font&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#2e8b57"&gt;&lt;b&gt;uint32_t&lt;/b&gt;&lt;/font&gt;&amp;nbsp;condexec_bits; &lt;font color="#0000ff"&gt;/*&lt;/font&gt;&lt;font color="#0000ff"&gt;&amp;nbsp;IT bits.&amp;nbsp;&amp;nbsp;cpsr[&lt;/font&gt;&lt;span style="background-color: #f2f2f2"&gt;&lt;font color="#ff00ff"&gt;15&lt;/font&gt;&lt;/span&gt;&lt;font color="#0000ff"&gt;:&lt;/font&gt;&lt;span style="background-color: #f2f2f2"&gt;&lt;font color="#ff00ff"&gt;10&lt;/font&gt;&lt;/span&gt;&lt;font color="#0000ff"&gt;,&lt;/font&gt;&lt;span style="background-color: #f2f2f2"&gt;&lt;font color="#ff00ff"&gt;26&lt;/font&gt;&lt;/span&gt;&lt;font color="#0000ff"&gt;:&lt;/font&gt;&lt;span style="background-color: #f2f2f2"&gt;&lt;font color="#ff00ff"&gt;25&lt;/font&gt;&lt;/span&gt;&lt;font color="#0000ff"&gt;].&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color="#0000ff"&gt;*/&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#0000ff"&gt;/*&lt;/font&gt;&lt;font color="#0000ff"&gt;&amp;nbsp;System control coprocessor (cp15) &lt;/font&gt;&lt;font color="#0000ff"&gt;*/&lt;/font&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#2e8b57"&gt;&lt;b&gt;struct&lt;/b&gt;&lt;/font&gt;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#2e8b57"&gt;&lt;b&gt;uint32_t&lt;/b&gt;&lt;/font&gt;&amp;nbsp;c0_cpuid;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#2e8b57"&gt;&lt;b&gt;uint32_t&lt;/b&gt;&lt;/font&gt;&amp;nbsp;c0_cachetype;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#2e8b57"&gt;&lt;b&gt;uint32_t&lt;/b&gt;&lt;/font&gt;&amp;nbsp;c0_c1[&lt;span style="background-color: #f2f2f2"&gt;&lt;font color="#ff00ff"&gt;8&lt;/font&gt;&lt;/span&gt;]; &lt;font color="#0000ff"&gt;/*&lt;/font&gt;&lt;font color="#0000ff"&gt;&amp;nbsp;Feature registers.&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color="#0000ff"&gt;*/&lt;/font&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#2e8b57"&gt;&lt;b&gt;uint32_t&lt;/b&gt;&lt;/font&gt;&amp;nbsp;c0_c2[&lt;span style="background-color: #f2f2f2"&gt;&lt;font color="#ff00ff"&gt;8&lt;/font&gt;&lt;/span&gt;]; &lt;font color="#0000ff"&gt;/*&lt;/font&gt;&lt;font color="#0000ff"&gt;&amp;nbsp;Instruction set registers.&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color="#0000ff"&gt;*/&lt;/font&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#2e8b57"&gt;&lt;b&gt;uint32_t&lt;/b&gt;&lt;/font&gt;&amp;nbsp;c1_sys; &lt;font color="#0000ff"&gt;/*&lt;/font&gt;&lt;font color="#0000ff"&gt;&amp;nbsp;System control register.&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color="#0000ff"&gt;*/&lt;/font&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#2e8b57"&gt;&lt;b&gt;uint32_t&lt;/b&gt;&lt;/font&gt;&amp;nbsp;c1_coproc; &lt;font color="#0000ff"&gt;/*&lt;/font&gt;&lt;font color="#0000ff"&gt;&amp;nbsp;Coprocessor access register.&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color="#0000ff"&gt;*/&lt;/font&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#2e8b57"&gt;&lt;b&gt;uint32_t&lt;/b&gt;&lt;/font&gt;&amp;nbsp;c1_xscaleauxcr; &lt;font color="#0000ff"&gt;/*&lt;/font&gt;&lt;font color="#0000ff"&gt;&amp;nbsp;XScale auxiliary control register.&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color="#0000ff"&gt;*/&lt;/font&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#2e8b57"&gt;&lt;b&gt;uint32_t&lt;/b&gt;&lt;/font&gt;&amp;nbsp;c2_base0; &lt;font color="#0000ff"&gt;/*&lt;/font&gt;&lt;font color="#0000ff"&gt;&amp;nbsp;MMU translation table base &lt;/font&gt;&lt;span style="background-color: #f2f2f2"&gt;&lt;font color="#ff00ff"&gt;0.&lt;/font&gt;&lt;/span&gt;&lt;font color="#0000ff"&gt;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color="#0000ff"&gt;*/&lt;/font&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#2e8b57"&gt;&lt;b&gt;uint32_t&lt;/b&gt;&lt;/font&gt;&amp;nbsp;c2_base1; &lt;font color="#0000ff"&gt;/*&lt;/font&gt;&lt;font color="#0000ff"&gt;&amp;nbsp;MMU translation table base &lt;/font&gt;&lt;span style="background-color: #f2f2f2"&gt;&lt;font color="#ff00ff"&gt;1.&lt;/font&gt;&lt;/span&gt;&lt;font color="#0000ff"&gt;&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color="#0000ff"&gt;*/&lt;/font&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#2e8b57"&gt;&lt;b&gt;uint32_t&lt;/b&gt;&lt;/font&gt;&amp;nbsp;c2_mask; &lt;font color="#0000ff"&gt;/*&lt;/font&gt;&lt;font color="#0000ff"&gt;&amp;nbsp;MMU translation table base mask.&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color="#0000ff"&gt;*/&lt;/font&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#2e8b57"&gt;&lt;b&gt;uint32_t&lt;/b&gt;&lt;/font&gt;&amp;nbsp;c2_data; &lt;font color="#0000ff"&gt;/*&lt;/font&gt;&lt;font color="#0000ff"&gt;&amp;nbsp;MPU data cachable bits.&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color="#0000ff"&gt;*/&lt;/font&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#2e8b57"&gt;&lt;b&gt;uint32_t&lt;/b&gt;&lt;/font&gt;&amp;nbsp;c2_insn; &lt;font color="#0000ff"&gt;/*&lt;/font&gt;&lt;font color="#0000ff"&gt;&amp;nbsp;MPU instruction cachable bits.&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color="#0000ff"&gt;*/&lt;/font&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#2e8b57"&gt;&lt;b&gt;uint32_t&lt;/b&gt;&lt;/font&gt;&amp;nbsp;c3; &lt;font color="#0000ff"&gt;/*&lt;/font&gt;&lt;font color="#0000ff"&gt;&amp;nbsp;MMU domain access control register&lt;/font&gt;&lt;br /&gt;&lt;font color="#0000ff"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;MPU write buffer control.&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color="#0000ff"&gt;*/&lt;/font&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#2e8b57"&gt;&lt;b&gt;uint32_t&lt;/b&gt;&lt;/font&gt;&amp;nbsp;c5_insn; &lt;font color="#0000ff"&gt;/*&lt;/font&gt;&lt;font color="#0000ff"&gt;&amp;nbsp;Fault status registers.&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color="#0000ff"&gt;*/&lt;/font&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#2e8b57"&gt;&lt;b&gt;uint32_t&lt;/b&gt;&lt;/font&gt;&amp;nbsp;c5_data;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#2e8b57"&gt;&lt;b&gt;uint32_t&lt;/b&gt;&lt;/font&gt;&amp;nbsp;c6_region[&lt;span style="background-color: #f2f2f2"&gt;&lt;font color="#ff00ff"&gt;8&lt;/font&gt;&lt;/span&gt;]; &lt;font color="#0000ff"&gt;/*&lt;/font&gt;&lt;font color="#0000ff"&gt;&amp;nbsp;MPU base/size registers.&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color="#0000ff"&gt;*/&lt;/font&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#2e8b57"&gt;&lt;b&gt;uint32_t&lt;/b&gt;&lt;/font&gt;&amp;nbsp;c6_insn; &lt;font color="#0000ff"&gt;/*&lt;/font&gt;&lt;font color="#0000ff"&gt;&amp;nbsp;Fault address registers.&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color="#0000ff"&gt;*/&lt;/font&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#2e8b57"&gt;&lt;b&gt;uint32_t&lt;/b&gt;&lt;/font&gt;&amp;nbsp;c6_data;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#2e8b57"&gt;&lt;b&gt;uint32_t&lt;/b&gt;&lt;/font&gt;&amp;nbsp;c9_insn; &lt;font color="#0000ff"&gt;/*&lt;/font&gt;&lt;font color="#0000ff"&gt;&amp;nbsp;Cache lockdown registers.&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color="#0000ff"&gt;*/&lt;/font&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#2e8b57"&gt;&lt;b&gt;uint32_t&lt;/b&gt;&lt;/font&gt;&amp;nbsp;c9_data;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#2e8b57"&gt;&lt;b&gt;uint32_t&lt;/b&gt;&lt;/font&gt;&amp;nbsp;c13_fcse; &lt;font color="#0000ff"&gt;/*&lt;/font&gt;&lt;font color="#0000ff"&gt;&amp;nbsp;FCSE PID.&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color="#0000ff"&gt;*/&lt;/font&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#2e8b57"&gt;&lt;b&gt;uint32_t&lt;/b&gt;&lt;/font&gt;&amp;nbsp;c13_context; &lt;font color="#0000ff"&gt;/*&lt;/font&gt;&lt;font color="#0000ff"&gt;&amp;nbsp;Context ID.&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color="#0000ff"&gt;*/&lt;/font&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#2e8b57"&gt;&lt;b&gt;uint32_t&lt;/b&gt;&lt;/font&gt;&amp;nbsp;c13_tls1; &lt;font color="#0000ff"&gt;/*&lt;/font&gt;&lt;font color="#0000ff"&gt;&amp;nbsp;User RW Thread register.&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color="#0000ff"&gt;*/&lt;/font&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#2e8b57"&gt;&lt;b&gt;uint32_t&lt;/b&gt;&lt;/font&gt;&amp;nbsp;c13_tls2; &lt;font color="#0000ff"&gt;/*&lt;/font&gt;&lt;font color="#0000ff"&gt;&amp;nbsp;User RO Thread register.&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color="#0000ff"&gt;*/&lt;/font&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#2e8b57"&gt;&lt;b&gt;uint32_t&lt;/b&gt;&lt;/font&gt;&amp;nbsp;c13_tls3; &lt;font color="#0000ff"&gt;/*&lt;/font&gt;&lt;font color="#0000ff"&gt;&amp;nbsp;Privileged Thread register.&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color="#0000ff"&gt;*/&lt;/font&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#2e8b57"&gt;&lt;b&gt;uint32_t&lt;/b&gt;&lt;/font&gt;&amp;nbsp;c15_cpar; &lt;font color="#0000ff"&gt;/*&lt;/font&gt;&lt;font color="#0000ff"&gt;&amp;nbsp;XScale Coprocessor Access Register &lt;/font&gt;&lt;font color="#0000ff"&gt;*/&lt;/font&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#2e8b57"&gt;&lt;b&gt;uint32_t&lt;/b&gt;&lt;/font&gt;&amp;nbsp;c15_ticonfig; &lt;font color="#0000ff"&gt;/*&lt;/font&gt;&lt;font color="#0000ff"&gt;&amp;nbsp;TI925T configuration byte.&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color="#0000ff"&gt;*/&lt;/font&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#2e8b57"&gt;&lt;b&gt;uint32_t&lt;/b&gt;&lt;/font&gt;&amp;nbsp;c15_i_max; &lt;font color="#0000ff"&gt;/*&lt;/font&gt;&lt;font color="#0000ff"&gt;&amp;nbsp;Maximum D-cache dirty line index.&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color="#0000ff"&gt;*/&lt;/font&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#2e8b57"&gt;&lt;b&gt;uint32_t&lt;/b&gt;&lt;/font&gt;&amp;nbsp;c15_i_min; &lt;font color="#0000ff"&gt;/*&lt;/font&gt;&lt;font color="#0000ff"&gt;&amp;nbsp;Minimum D-cache dirty line index.&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color="#0000ff"&gt;*/&lt;/font&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#2e8b57"&gt;&lt;b&gt;uint32_t&lt;/b&gt;&lt;/font&gt;&amp;nbsp;c15_threadid; &lt;font color="#0000ff"&gt;/*&lt;/font&gt;&lt;font color="#0000ff"&gt;&amp;nbsp;TI debugger thread-ID.&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color="#0000ff"&gt;*/&lt;/font&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;} cp15;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#2e8b57"&gt;&lt;b&gt;struct&lt;/b&gt;&lt;/font&gt;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#2e8b57"&gt;&lt;b&gt;uint32_t&lt;/b&gt;&lt;/font&gt;&amp;nbsp;other_sp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#2e8b57"&gt;&lt;b&gt;uint32_t&lt;/b&gt;&lt;/font&gt;&amp;nbsp;vecbase;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#2e8b57"&gt;&lt;b&gt;uint32_t&lt;/b&gt;&lt;/font&gt;&amp;nbsp;basepri;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#2e8b57"&gt;&lt;b&gt;uint32_t&lt;/b&gt;&lt;/font&gt;&amp;nbsp;control;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#2e8b57"&gt;&lt;b&gt;int&lt;/b&gt;&lt;/font&gt;&amp;nbsp;current_sp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#2e8b57"&gt;&lt;b&gt;int&lt;/b&gt;&lt;/font&gt;&amp;nbsp;exception;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#2e8b57"&gt;&lt;b&gt;int&lt;/b&gt;&lt;/font&gt;&amp;nbsp;pending_exception;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#2e8b57"&gt;&lt;b&gt;void&lt;/b&gt;&lt;/font&gt;&amp;nbsp;*nvic;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;} v7m;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#0000ff"&gt;/*&lt;/font&gt;&lt;font color="#0000ff"&gt;&amp;nbsp;Coprocessor IO used by peripherals &lt;/font&gt;&lt;font color="#0000ff"&gt;*/&lt;/font&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#2e8b57"&gt;&lt;b&gt;struct&lt;/b&gt;&lt;/font&gt;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ARMReadCPFunc *cp_read;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ARMWriteCPFunc *cp_write;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#2e8b57"&gt;&lt;b&gt;void&lt;/b&gt;&lt;/font&gt;&amp;nbsp;*opaque;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;} cp[&lt;span style="background-color: #f2f2f2"&gt;&lt;font color="#ff00ff"&gt;15&lt;/font&gt;&lt;/span&gt;];&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#0000ff"&gt;/*&lt;/font&gt;&lt;font color="#0000ff"&gt;&amp;nbsp;Internal CPU feature flags.&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color="#0000ff"&gt;*/&lt;/font&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#2e8b57"&gt;&lt;b&gt;uint32_t&lt;/b&gt;&lt;/font&gt;&amp;nbsp;features;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#0000ff"&gt;/*&lt;/font&gt;&lt;font color="#0000ff"&gt;&amp;nbsp;Callback for vectored interrupt controller.&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color="#0000ff"&gt;*/&lt;/font&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#2e8b57"&gt;&lt;b&gt;int&lt;/b&gt;&lt;/font&gt;&amp;nbsp;(*get_irq_vector)(&lt;font color="#2e8b57"&gt;&lt;b&gt;struct&lt;/b&gt;&lt;/font&gt;&amp;nbsp;CPUARMState *);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#2e8b57"&gt;&lt;b&gt;void&lt;/b&gt;&lt;/font&gt;&amp;nbsp;*irq_opaque;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#0000ff"&gt;/*&lt;/font&gt;&lt;font color="#0000ff"&gt;&amp;nbsp;exception/interrupt handling &lt;/font&gt;&lt;font color="#0000ff"&gt;*/&lt;/font&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#2e8b57"&gt;&lt;b&gt;jmp_buf&lt;/b&gt;&lt;/font&gt;&amp;nbsp;jmp_env;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#2e8b57"&gt;&lt;b&gt;int&lt;/b&gt;&lt;/font&gt;&amp;nbsp;exception_index;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#2e8b57"&gt;&lt;b&gt;int&lt;/b&gt;&lt;/font&gt;&amp;nbsp;interrupt_request;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#2e8b57"&gt;&lt;b&gt;int&lt;/b&gt;&lt;/font&gt;&amp;nbsp;user_mode_only;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#2e8b57"&gt;&lt;b&gt;int&lt;/b&gt;&lt;/font&gt;&amp;nbsp;halted;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#0000ff"&gt;/*&lt;/font&gt;&lt;font color="#0000ff"&gt;&amp;nbsp;VFP coprocessor state.&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color="#0000ff"&gt;*/&lt;/font&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#2e8b57"&gt;&lt;b&gt;struct&lt;/b&gt;&lt;/font&gt;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;float64 regs[&lt;span style="background-color: #f2f2f2"&gt;&lt;font color="#ff00ff"&gt;32&lt;/font&gt;&lt;/span&gt;];&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#2e8b57"&gt;&lt;b&gt;uint32_t&lt;/b&gt;&lt;/font&gt;&amp;nbsp;xregs[&lt;span style="background-color: #f2f2f2"&gt;&lt;font color="#ff00ff"&gt;16&lt;/font&gt;&lt;/span&gt;];&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#0000ff"&gt;/*&lt;/font&gt;&lt;font color="#0000ff"&gt;&amp;nbsp;We store these fpcsr fields separately for convenience.&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color="#0000ff"&gt;*/&lt;/font&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#2e8b57"&gt;&lt;b&gt;int&lt;/b&gt;&lt;/font&gt;&amp;nbsp;vec_len;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#2e8b57"&gt;&lt;b&gt;int&lt;/b&gt;&lt;/font&gt;&amp;nbsp;vec_stride;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#0000ff"&gt;/*&lt;/font&gt;&lt;font color="#0000ff"&gt;&amp;nbsp;Temporary variables if we don't have spare fp regs.&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color="#0000ff"&gt;*/&lt;/font&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;float32 tmp0s, tmp1s;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;float64 tmp0d, tmp1d;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#0000ff"&gt;/*&lt;/font&gt;&lt;font color="#0000ff"&gt;&amp;nbsp;scratch space when Tn are not sufficient.&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color="#0000ff"&gt;*/&lt;/font&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#2e8b57"&gt;&lt;b&gt;uint32_t&lt;/b&gt;&lt;/font&gt;&amp;nbsp;scratch[&lt;span style="background-color: #f2f2f2"&gt;&lt;font color="#ff00ff"&gt;8&lt;/font&gt;&lt;/span&gt;];&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;float_status fp_status;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;} vfp;&lt;br /&gt;&lt;font color="#a020f0"&gt;#if defined(CONFIG_USER_ONLY)&lt;/font&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#2e8b57"&gt;&lt;b&gt;struct&lt;/b&gt;&lt;/font&gt;&amp;nbsp;mmon_state *mmon_entry;&lt;br /&gt;&lt;font color="#a020f0"&gt;#else&lt;/font&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#2e8b57"&gt;&lt;b&gt;uint32_t&lt;/b&gt;&lt;/font&gt;&amp;nbsp;mmon_addr;&lt;br /&gt;&lt;font color="#a020f0"&gt;#endif&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#0000ff"&gt;/*&lt;/font&gt;&lt;font color="#0000ff"&gt;&amp;nbsp;iwMMXt coprocessor state.&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color="#0000ff"&gt;*/&lt;/font&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#2e8b57"&gt;&lt;b&gt;struct&lt;/b&gt;&lt;/font&gt;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#2e8b57"&gt;&lt;b&gt;uint64_t&lt;/b&gt;&lt;/font&gt;&amp;nbsp;regs[&lt;span style="background-color: #f2f2f2"&gt;&lt;font color="#ff00ff"&gt;16&lt;/font&gt;&lt;/span&gt;];&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#2e8b57"&gt;&lt;b&gt;uint64_t&lt;/b&gt;&lt;/font&gt;&amp;nbsp;val;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#2e8b57"&gt;&lt;b&gt;uint32_t&lt;/b&gt;&lt;/font&gt;&amp;nbsp;cregs[&lt;span style="background-color: #f2f2f2"&gt;&lt;font color="#ff00ff"&gt;16&lt;/font&gt;&lt;/span&gt;];&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;} iwmmxt;&lt;br /&gt;&lt;br /&gt;&lt;font color="#a020f0"&gt;#if defined(CONFIG_USER_ONLY)&lt;/font&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#0000ff"&gt;/*&lt;/font&gt;&lt;font color="#0000ff"&gt;&amp;nbsp;For usermode syscall translation.&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color="#0000ff"&gt;*/&lt;/font&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#2e8b57"&gt;&lt;b&gt;int&lt;/b&gt;&lt;/font&gt;&amp;nbsp;eabi;&lt;br /&gt;&lt;font color="#a020f0"&gt;#endif&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;CPU_COMMON&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#0000ff"&gt;/*&lt;/font&gt;&lt;font color="#0000ff"&gt;&amp;nbsp;These fields after the common ones so they are preserved on reset.&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;font color="#0000ff"&gt;*/&lt;/font&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#2e8b57"&gt;&lt;b&gt;int&lt;/b&gt;&lt;/font&gt;&amp;nbsp;ram_size;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#2e8b57"&gt;&lt;b&gt;const&lt;/b&gt;&lt;/font&gt;&amp;nbsp;&lt;font color="#2e8b57"&gt;&lt;b&gt;char&lt;/b&gt;&lt;/font&gt;&amp;nbsp;*kernel_filename;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#2e8b57"&gt;&lt;b&gt;const&lt;/b&gt;&lt;/font&gt;&amp;nbsp;&lt;font color="#2e8b57"&gt;&lt;b&gt;char&lt;/b&gt;&lt;/font&gt;&amp;nbsp;*kernel_cmdline;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#2e8b57"&gt;&lt;b&gt;const&lt;/b&gt;&lt;/font&gt;&amp;nbsp;&lt;font color="#2e8b57"&gt;&lt;b&gt;char&lt;/b&gt;&lt;/font&gt;&amp;nbsp;*initrd_filename;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#2e8b57"&gt;&lt;b&gt;int&lt;/b&gt;&lt;/font&gt;&amp;nbsp;board_id;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;target_phys_addr_t loader_start;&lt;br /&gt;} CPUARMState;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;font color="#a020f0"&gt;#define CPUState CPUARMState&lt;/font&gt;&lt;/font&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3477330834625238216-58334294560749727?l=qemumemo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://qemumemo.blogspot.com/feeds/58334294560749727/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://qemumemo.blogspot.com/2008/12/cpustate.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3477330834625238216/posts/default/58334294560749727'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3477330834625238216/posts/default/58334294560749727'/><link rel='alternate' type='text/html' href='http://qemumemo.blogspot.com/2008/12/cpustate.html' title='CPUState'/><author><name>aloha</name><uri>http://www.blogger.com/profile/17250121836567925230</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3477330834625238216.post-3148007389630720639</id><published>2008-12-22T10:38:00.010+09:00</published><updated>2008-12-22T14:48:24.712+09:00</updated><title type='text'>QEMU 0.9.1 のビルド</title><content type='html'>MinGW + MSYS 環境は、&lt;a href="http://www.mingw.org/wiki/MSYS"&gt;ここらへんを参考にしつつ&lt;/a&gt; 作る。&lt;br /&gt;&lt;br /&gt;MinGW 5.1.4 のインストーラを使ってデフォルトインストール (/c/mingw 以下)&lt;br /&gt;MSYS 1.0.10 のインストーラを使ってデフォルトインストール) (/c/msys/1.0 以下)&lt;br /&gt;&lt;br /&gt;MSYS Core 1.0.11 と MSYS DTK 1.0 を /c/msys 以下に適宜ディレクトリ構成を合わせて展開する。&lt;br /&gt;&lt;br /&gt;これだけだと unistd.h が古くて、QEMU をビルドする時に getopts で引っかかるので、mingwrt-3.15.1-mingw32-dev.tar.gz  と mingwrt-3.15.1-mingw32-dll.tar.gz を /mingw 以下に適宜ディレクトリ構成を合わせて展開しておく。&lt;br /&gt;&lt;br /&gt;&lt;a href="http://sourceforge.jp/projects/mingw/releases/35393"&gt;http://sourceforge.jp/projects/mingw/releases/35393&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;SDL を ./configure --prefi=/usr/local で install （これはどこでも良いと思う）。&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.libsdl.org/download-1.2.php"&gt;SDL-1.2.13.tar.gz&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Zlib を ./configure --prefix=/mingw で install（mingw 以下じゃないと見つけてくれない）。&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.zlib.net/"&gt;zlib-1.2.3.tar.gz&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;QEMU を ./configure --prefix=/usr/local/QEMU などに make ; make install&lt;br /&gt;&lt;br /&gt;&lt;a href="http://bellard.org/qemu/download.html"&gt;qemu-0.9.1.tar.gz&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;ただし qemu-0.9.1/hw/omap.c の localtime_r と gmtime_r を使っているところ (4671, 4733, 4750 行目)&lt;br /&gt;を comment out しておかないとコケる。&lt;br /&gt;&lt;br /&gt;これで、とりあえずビルドは通るはず （各ターゲットの動作検証はしてない）&lt;br /&gt;&lt;br /&gt;CPU のシミュレーションだけを行いたい場合は、--disable-sdl で、SDL をインストールしなくてもビルドできると思う。&lt;br /&gt;あと、使いたいターゲットだけをビルドした方が良いと思う。&lt;br /&gt;&lt;br /&gt;configure option&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;blockquote&gt;$ ./configure --help&lt;br /&gt;&lt;br /&gt;Usage: configure [options]&lt;br /&gt;Options: [defaults in brackets after descriptions]&lt;br /&gt;&lt;br /&gt;Standard options:&lt;br /&gt; --help                   print this message&lt;br /&gt; --prefix=PREFIX          install in PREFIX []&lt;br /&gt; --interp-prefix=PREFIX   where to find shared libraries, etc.&lt;br /&gt;                          use %M for cpu name [/usr/gnemul/qemu-%M]&lt;br /&gt; --target-list=LIST       set target list []&lt;br /&gt;&lt;br /&gt;kqemu kernel acceleration support:&lt;br /&gt; --disable-kqemu          disable kqemu support&lt;br /&gt;&lt;br /&gt;Advanced options (experts only):&lt;br /&gt; --source-path=PATH       path of source code [/home/aloha/work/QEMU/qemu-0.9.1]&lt;br /&gt; --cross-prefix=PREFIX    use PREFIX for compile tools []&lt;br /&gt; --cc=CC                  use C compiler CC [gcc]&lt;br /&gt; --host-cc=CC             use C compiler CC [gcc] for dyngen etc.&lt;br /&gt; --make=MAKE              use specified make [make]&lt;br /&gt; --install=INSTALL        use specified install [install]&lt;br /&gt; --static                 enable static build [no]&lt;br /&gt; --disable-werror         disable compilation abort on warning&lt;br /&gt; --disable-sdl            disable SDL&lt;br /&gt; --enable-cocoa           enable COCOA (Mac OS X only)&lt;br /&gt; --enable-mingw32         enable Win32 cross compilation with mingw32&lt;br /&gt; --enable-adlib           enable Adlib emulation&lt;br /&gt; --enable-coreaudio       enable Coreaudio audio driver&lt;br /&gt; --enable-alsa            enable ALSA audio driver&lt;br /&gt; --enable-fmod            enable FMOD audio driver&lt;br /&gt; --enable-dsound          enable DirectSound audio driver&lt;br /&gt; --disable-vnc-tls        disable TLS encryption for VNC server&lt;br /&gt; --enable-system          enable all system emulation targets&lt;br /&gt; --disable-system         disable all system emulation targets&lt;br /&gt; --enable-linux-user      enable all linux usermode emulation targets&lt;br /&gt; --disable-linux-user     disable all linux usermode emulation targets&lt;br /&gt; --enable-darwin-user     enable all darwin usermode emulation targets&lt;br /&gt; --disable-darwin-user    disable all darwin usermode emulation targets&lt;br /&gt; --fmod-lib               path to FMOD library&lt;br /&gt; --fmod-inc               path to FMOD includes&lt;br /&gt; --enable-uname-release=R Return R for uname -r in usermode emulation&lt;br /&gt; --sparc_cpu=V            Build qemu for Sparc architecture v7, v8, v8plus, v8plusa, v9&lt;br /&gt;&lt;br /&gt;NOTE: The object files are built at the place where configure is launched&lt;/blockquote&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;なぜか --target-list=arm-softmmu でやったら undefined reference to `ffs' というエラーが出たので、qemu-0.9.1/hw/max7310.c や sd.c などの該当行を comment out した。&lt;br /&gt;&lt;br /&gt;--disable-sdl --disable-gfx-check などとすると、グラフィカルアウトプットを切れるみたい。&lt;br /&gt;（ただし、QEMU のサイトのサンプルイメージは、-nographic では起動しなかった）&lt;br /&gt;&lt;br /&gt;Makefile だけ編集してもダメ。confighost.mak なども変更しないと反映されない。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3477330834625238216-3148007389630720639?l=qemumemo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://qemumemo.blogspot.com/feeds/3148007389630720639/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://qemumemo.blogspot.com/2008/12/qemu-091.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3477330834625238216/posts/default/3148007389630720639'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3477330834625238216/posts/default/3148007389630720639'/><link rel='alternate' type='text/html' href='http://qemumemo.blogspot.com/2008/12/qemu-091.html' title='QEMU 0.9.1 のビルド'/><author><name>aloha</name><uri>http://www.blogger.com/profile/17250121836567925230</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry></feed>
