MIPS(2)

朝は、『梅ちゃん先生』を見て、その後もチャンネルはそのままで、あさいち って流れが 多いようです。 たまに、BSで先行してやってる、梅ちゃん を見てから、地デジの梅ちゃんで本番を見るって パターンもあるみたい。両方共見逃した時は、お昼に見るか、土曜日にやってる、1週間のまとめ と復習を見てるみたい。随分、しつこいな。まあ、おいらは興味ないんで、どうでもいいけど。 おいらが見るのは、ワールドライフぐらいかな。

で、あさいちを見てた女房が、最近、柳沢さん出てないけど、ちいさんみたいに病気にでも なっちゃったの?

で、調査を命じられましたよ。そんなクイズ番組みたいなのは、DeepBlueのワトスン君にでも 聞いてくれ、、、とは言えないので、ぐぐる先生に聞いてみましたよ。

NHKあさイチの柳沢さんがいませんがどうしたのでしょうか? とか、あさイチ 柳沢 降板 とかが出てきた。

偉くなったんで、お茶の間では、余りくつろげませんって事だな。そんなに働かなくても。。。 早く、リタイアして、JA7JJN を、田舎である会津若松からやったらどうですか。 田舎は寒くていやだってんなら、VKとかMAへ移住して、ゴルフ三昧と無線とかどうですか?

おいらは田舎で、読書、パソコン、時々無線、温泉とかやってますよ。

gxemul

前回、MIPS版のLinuxをQEMU上で動かした。けど、このLinuxはテスト用って事で、いろいろ 遊ぼうと思うと不便をきたす。最低でも、コンパイラとgdbぐらいは欲しいぞ。

そんじゃ、普通のOSを入れちゃえばって事になる。デフォでコンパイラ系が入ってるOSと言ったら BSD系しかない。そうだ、CPUの博物館である、 NetBSDに行って、対応機種一覧でも眺めてみるか。 そして、良さそうなものをお持ち帰り。

qemu-system-mipsel -hda disk.img -cdrom catscd-5.1.iso  -boot d -m 128 -nographic -monitor telnet::4444,server,nowait

でも、起動しないんだよな。やっぱり白ROMが入っているような、怪しいマシンじゃダメなのかな。 諦めきれずに、博物館をうろうろしてたら、 エミュレートされたハードウェア上で NetBSD を動かす なんて言う、そそられるパンフレットが置いてあるじゃないですか。熟読しましたよ。世界が 広がるなあ。

比較表を見るまでもなく、Gxemulが良さそうだ。NetBSDで パッケージになってるって事は、BSD3兄弟のうちのFreeBSDにも有るに違いない。 有ったよ。

[sakae@secd /usr/ports/emulators/gxemul]$ cat pkg-descr
GXemul is a free instruction-level machine emulator, emulating not only the
CPU, but also other hardware components, making it possible to use the emulator
to run unmodified operating systems such as NetBSD, OpenBSD, or Linux.

A few different machine types are emulated. The following machine types are
emulated well enough to run at least one "guest OS":

 * ARM: CATS (NetBSD/cats, OpenBSD/cats), IQ80321 (NetBSD/evbarm), NetWinder
   (NetBSD/netwinder)
 * MIPS: DECstation 5000/200 (NetBSD/pmax, OpenBSD/pmax, Ultrix,
   Linux/DECstation, Sprite), Acer Pica-61 (NetBSD/arc), NEC MobilePro 770,
   780, 800, 880 (NetBSD/hpcmips), Cobalt (NetBSD/cobalt), Malta
   (NetBSD/evbmips, Linux/Malta) Algorithmics P5064 (NetBSD/algor), SGI
   O2 (aka IP32) (NetBSD/sgi)
 * PowerPC: IBM 6050/6070 (PReP, PowerPC Reference Platform) (NetBSD/prep),
   MacPPC (generic "G4" Macintosh) (NetBSD/macppc)
 * SuperH: Sega Dreamcast (NetBSD/dreamcast, Linux/dreamcast),
   Landisk (OpenBSD/landisk)

WWW: http://gavare.se/gxemul/

喜びいさんで入れたのは、言うまでもない。

cobalt

はて、何をいれようか。 GXemul: Installing and running 'guest OSes' を、1分眺めて、cobaltに決定。元マシンは、コバルト色した4角な箱ね。昔、一度だけ実物を 見た事がある。Webサーバーとして活躍してたなあ。これを選んだのは、実物を知ってた(見た)から。人生なんて、まあ、 そんなもんさ。

入れてみた。NetBSDのインストールなんて何年ぶりだろう。それでも迷う事なくインストール 出来たよ。でも、残念ながらNICは付いていなかった。xterm上で動く端末のみなんだ。これじゃ、 この駄文を書くには、ちょっと役不足だな。一応入れたって事で、魚拓だけ。

mips$ dmesg
 :
NetBSD 5.0.1 (GENERIC) #0: Wed Jul 29 19:14:34 UTC 2009
        builds@b8.netbsd.org:/home/builds/ab/netbsd-5-0-1-RELEASE/cobalt/200907292356Z-obj/home/builds/ab/netbsd-5-0-1-RELEASE/src/sys/arch/cobalt/compile/GENERIC

Cobalt Qube 2
total memory = 32768 KB
avail memory = 27908 KB
timecounter: Timecounters tick every 10.000 msec
mainbus0 (root)
com0 at mainbus0 addr 0x1c800000 level 3: ns16550a, working fifo
com0: console
cpu0 at mainbus0: QED RM5200 CPU (0x28a0) Rev. 10.0 with built-in FPU Rev. 1.0
cpu0: 32KB/32B 2-way set-associative L1 Instruction cache, 48 TLB entries
cpu0: 32KB/32B 2-way set-associative write-back L1 Data cache

mcclock0 at mainbus0 addr 0x10000070: mc146818 compatible time-of-day clock
panel0 at mainbus0 addr 0x1f000000panel0: LCD not responding or unconnected
  :
wd0 at atabus0 drive 0: <nbsd_cobalt.img>
wd0: drive supports 128-sector PIO transfers, chs addressing
wd0: 2637 MB, 5358 cyl, 16 head, 63 sec, 512 bytes/sect x 5400864 sectors
wd0: 32-bit data port
wd0: drive supports PIO mode 4
Kernelized RAIDframe activated
boot device: wd0
root on wd0a dumps on wd0b
root file system type: ffs

pmax

これ、今は亡き Digital Equipment Corporationが出していたワークステーションです。 これなら、間違ってもNICは付いているだろうと言う目論見が有ります。

で、NICはちゃんと付いていましたよ。

DECstation 5000/200 (3MAX)
total memory = 65536 KB
avail memory = 59644 KB
cpu0 at mainbus0: MIPS R3000 CPU (0x220) Rev. 2.0 with MIPS R3010 FPC Rev. 4.0
cpu0: 4KB/4B direct-mapped Instruction cache, 64 TLB entries
cpu0: 4KB/4B direct-mapped write-through Data cache
le0 at tc0 slot 6 offset 0x0: address 10:20:30:00:00:10
le0: 32 receive buffers, 8 transmit buffers

これならNICをちゃんと設定すれば、外側(のFreeBSD)から、sshで入れると期待したんだけど、 何をやってもダメだった。NetBSD側から外へは行けるんで、まっいいか。

pmax$ grep 10.0.0 ./rc.conf
defaultroute="10.0.0.254"
ifconfig_le0="10.0.0.27 netmask 0xffffff00"

これ、外へ出る設定ね。gxemulがNATをやってくれてるんだな。 ちょいと嬉しい事に、シリアル接続も出来るんで、わざわざ、FreeBSDのXを上げる必要は無い。 その代わり、CTRL-Cで、gxemulのモニターモードが起動しちゃうんで、ちょいと注意は 必要ね。おっと、シリアルラインがPuTTYに接続されるんだけど、25行モードになってたので、.profile を調教したよ。

export TERM=xterm
stty rows 38

MIPS語

記念に、MIPSのアセンブラでも眺めてみるか。例によって、sasagawa888さんのSchemeです。 assqがオリジナル版だと、しっかりcoreを吐いてくれました。

int macronamep(int sym)
{
41520c94:       3c1c0006        lui     gp,0x6
  415210:       279c0194        addiu   gp,gp,404
  415214:       0399e021        addu    gp,gp,t9
  415218:       27bdffd0        addiu   sp,sp,-48
  41521c:       afbf002c        sw      ra,44(sp)
  415220:       afbe0028        sw      s8,40(sp)
  415224:       03a0f021        move    s8,sp
  415228:       afbc0010        sw      gp,16(sp)
  41522c:       afc40030        sw      a0,48(s8)
    int val;

    val = assq(sym, G);
  415230:       8f828eb4        lw      v0,-29004(gp)
  415234:       00000000        nop
  415238:       8c420000        lw      v0,0(v0)
  41523c:       8fc40030        lw      a0,48(s8)
  415240:       00402821        move    a1,v0
  415244:       8f998d08        lw      t9,-29432(gp)
  415248:       00000000        nop
  41524c:       0320f809        jalr    t9
  415250:       00000000        nop
  415254:       8fdc0010        lw      gp,16(s8)
  415258:       afc20018        sw      v0,24(s8)
    if (val == 0)
  41525c:       8fc20018        lw      v0,24(s8)
  415260:       00000000        nop
  415264:       14400004        bnez    v0,415278 <macronamep+0x6c>
  415268:       00000000        nop
        return (0);
  41526c:       afc00020        sw      zero,32(s8)
  415270:       10000016        b       4152cc <macronamep+0xc0>
  415274:       00000000        nop
    if (IS_MACRO(cdr(val)))
  415278:       8fc40018        lw      a0,24(s8)
  41527c:       8f998e70        lw      t9,-29072(gp)
  415280:       00000000        nop
  415284:       0320f809        jalr    t9
  415288:       00000000        nop
  41528c:       8fdc0010        lw      gp,16(s8)
  415290:       00000000        nop
  415294:       8f849000        lw      a0,-28672(gp)
  415298:       00021900        sll     v1,v0,0x4
  41529c:       00031080        sll     v0,v1,0x2
  4152a0:       00431023        subu    v0,v0,v1
  4152a4:       00441021        addu    v0,v0,a0
  4152a8:       8c430000        lw      v1,0(v0)
  4152ac:       24020010        li      v0,16
  4152b0:       14620005        bne     v1,v0,4152c8 <macronamep+0xbc>
  4152b4:       00000000        nop
        return (1);
  4152b8:       24020001        li      v0,1
  4152bc:       afc20020        sw      v0,32(s8)
  4152c0:       10000002        b       4152cc <macronamep+0xc0>
  4152c4:       00000000        nop
    else
        return (0);
  4152c8:       afc00020        sw      zero,32(s8)
  4152cc:       8fc20020        lw      v0,32(s8)
}
  4152d0:       03c0e821        move    sp,s8
  4152d4:       8fbf002c        lw      ra,44(sp)
  4152d8:       8fbe0028        lw      s8,40(sp)
  4152dc:       27bd0030        addiu   sp,sp,48
  4152e0:       03e00008        jr      ra
  4152e4:       00000000        nop

gccのバージョンは

pmax$ gcc -v
Using built-in specs.
Target: mipsel--netbsd
Configured with: /usr/src/tools/gcc/../../gnu/dist/gcc4/configure --enable-long-long --disable-multilib --enable-threads --disable-symvers --build=x86_64-unknown-netbsd4.99.72 --host=mipsel--netbsd --target=mipsel--netbsd --enable-__cxa_atexit
Thread model: posix
gcc version 4.1.3 20080704 prerelease (NetBSD nb2 20081120)

再びcobalt

上記で、cobaltはネットが使えない(そもそもNICが付いていない)からと諦めていたけど、 docを読んでいたら、外からファイルを読み込む方法が載ってた。

gxemul -x -E cobalt -d nbsd_cobalt.img -d simp.tgz netbsd-GENERIC.gz

こんな風に、cobaltの中へ送り込みたいやつ(simp.tgz)用意し、-d で2nd Diskとして接続。 そうすると、gxemulの制御パネルに、こんなメッセージが出てくる。

GXemul 0.6.0    Copyright (C) 2003-2010  Anders Gavare
Read the source code and/or documentation for other Copyright messages.

Simple setup...
    net:
        simulated network: 10.0.0.0/8 (max outgoing: TCP=100, UDP=100)
        simulated gateway+nameserver: 10.0.0.254 (60:50:40:30:20:10)
        simulated nameserver uses real nameserver 192.168.136.2
    machine:
        memory: 32 MB
        cpu0: RM5200 (I+D = 32+32 KB)
        machine: Cobalt
        bootstring: root=/dev/hda1 ro
        diskimage: nbsd_cobalt.img
            IDE DISK id 0, read/write, 2637 MB (5400864 sectors)
        diskimage: simp.tgz
            IDE DISK id 1, read/write, 0 MB (68 sectors)
        gunziping netbsd-GENERIC.gz
        loading /tmp/gxemul.bAznpPUpWNvy
        removing /tmp/gxemul.bAznpPUpWNvy
        cpu0: starting at 0xffffffff80001000 (gp=0xffffffff803a04a0)

NOTE: This is a LEGACY emulation mode.

こうしておいてから、やおら、wd1dをテープと思って展開してやるんだ。

mips# tar zxvf /dev/wd1d
./Simple
./Simple/cell.c
./Simple/compute.c
./Simple/Makefile
./Simple/function.c
./Simple/list.c
./Simple/main.c
./Simple/README
./Simple/tags
./Simple/z.c
./Simple/simpmacs.scm
./Simple/test
./Simple/simp.h
./Simple/conv.sh
./Simple/test/math-test.scm
./Simple/test/mult-values.scm
./Simple/test/simp-test.scm
./Simple/test/cont-test.scm
gzip: (stdin): trailing garbage ignored
tar: ustar vol 1, 18 files, 184320 bytes read, 0 bytes written in 1 secs (184320
 bytes/sec)

面白いな。こういう使い方が出来るとは。で、逆にcobalt側から外側へ輸出出来るかと思って、

mips# tar zcvf /dev/wd1d ./Simple/

とかやったら、ちゃんと出来上がっていたよ。

[sakae@secd ~/cobalt]$ tar ztvf simp.tgz
drwxr-xr-x  0 sakae  users       0  7月 30  2009 ./Simple
-rw-r--r--  0 sakae  users   30535  5月 16 11:48 ./Simple/compute.c
-rw-r--r--  0 sakae  users    7670  5月 21 10:25 ./Simple/cell.c
  :
-rw-r--r--  0 sakae  users   73820  7月 30  2009 ./Simple/compute.o
-rwxr-xr-x  0 sakae  users  292993  7月 30  2009 ./Simple/simp
-rw-r--r--  0 sakae  users 1434372  7月 30  2009 ./Simple/MIPS-LOG
tar: Truncated input file (needed 1434624 bytes, only 0 available)
tar: Error exit delayed from previous errors.

タイムスタンプが可笑しいのは、許してね。

gxemul monitor

マシンを止めると、モニタのプロンプトが出てきて、さーさー、コマンドを打ち込めって 言ってるよ。どんなコマンドが有るかな?

GXemul> help
Available commands:
  allsettings                   show all settings
  breakpoint ...                manipulate breakpoints
  continue                      continue execution
  device ...                    show info about (or manipulate) devices
  dump [addr [endaddr]]         dump memory contents in hex and ASCII
  emul                          print a summary of the current emulation
  focus x[,y[,z]]               changes focus to cpu x, machine x, emul z
  help                          print this help message
  itrace                        toggle instruction_trace on or off
  lookup name|addr              lookup a symbol by name or address
  machine                       print a summary of the current machine
  ninstrs [on|off]              toggle (set or unset) show_nr_of_instructions
  pause cpuid                   pause (or unpause) a CPU
  print expr                    evaluate an expression without side-effects
  put [b|h|w|d|q] addr, data    modify emulated memory contents
  quiet [on|off]                toggle quiet_mode on or off
  quit                          quit the emulator
  reg [cpuid][,c]               show GPRs (or coprocessor c's registers)
  step [n]                      single-step one (or n) instruction(s)
  tlbdump [cpuid][,r]           dump TLB contents (add ',r' for raw data)
  trace [on|off]                toggle show_trace_tree on or off
  unassemble [addr [endaddr]]   dump memory contents as instructions
  version                       print version information
  x = expr                      generic assignment

In generic assignments, x must be a register or other writable settings
variable, and expr can contain registers/settings, numeric values, or symbol
names, in combination with parenthesis and + - * / & % ^ | operators.
In case there are multiple matches (i.e. a symbol that has the same name as a
register), you may add a prefix character as a hint: '#' for registers, '@'
for symbols, and '$' for numeric values. Use 0x for hexadecimal values.

色々と試したくなるのは、おいらのねっちっこい性だ。

GXemul> reg
cpu0:    pc = 0xffffffff800f0e1c    <com_common_getc+0xa0>
cpu0:    hi = 0x000000000002ee00    lo = 0x0000000000029040
cpu0:                               s0 = 0xffffffff803bc0d0
cpu0:    at = 0xffffffff803e0000    s1 = 0x0000000000000001
cpu0:    v0 = 0x0000000000000000    s2 = 0x0000000000001a00
cpu0:    v1 = 0xffffffff80390fec    s3 = 0x00000000000000d0
cpu0:    a0 = 0x0000000000000001    s4 = 0xffffffff816a95d8
cpu0:    a1 = 0xffffffffbc800000    s5 = 0x0000000000000808
cpu0:    a2 = 0xffffffff80390000    s6 = 0x000000007ddeda40
cpu0:    a3 = 0x0000000000000000    s7 = 0xffffffff810b1aa0
cpu0:    t0 = 0x0000000000000000    t8 = 0x0000000000000000
cpu0:    t1 = 0xffffffff803e3b50    t9 = 0xffffffff800f0ed8
cpu0:    t2 = 0xffffffff803e3b50    k0 = 0x000000000007d3df
cpu0:    t3 = 0x0000000051eb851f    k1 = 0x000000000007d19f
cpu0:    t4 = 0xffffffffc3f11df8    gp = 0xffffffff803a04a0
cpu0:    t5 = 0xffffffffc3627ef0    sp = 0xffffffffc3f11e18
cpu0:    t6 = 0xffffffffffffffff    fp = 0x0000000000000000
cpu0:    t7 = 0xffffffffffffffff    ra = 0xffffffff800f0da0
GXemul> reg ,c
cpu0:    index =         0x00000000   random =         0x00000009
cpu0: entrylo0 = 0x000000000007d3df entrylo1 = 0x000000000007d19f
cpu0:  context = 0x000000000061b1e0 pagemask = 0x0000000000000000
cpu0:    wired =         0x00000001  reserv7 = 0x0000000000000000
cpu0: badvaddr = 0xffffffffc363d0b4    count =         0xcc8ca927
cpu0:  entryhi = 0xc00000ffc363c07d  compare =         0xa0dd8359
cpu0:   status = 0x0000000000000001    cause = 0x0000000000008008
cpu0:      epc = 0xffffffff8021b6c0     prid = 0x00000000000028a0
cpu0:   config = 0x00000000000246f2   lladdr = 0x00000000f8039559
cpu0:  watchlo = 0x0000000000000000  watchhi = 0x0000000000000000
cpu0: xcontext = 0x00000001ffe1b1e0 reserv21 = 0x0000000000000000
cpu0: reserv22 = 0x0000000000000000    debug = 0x0000000000000000
cpu0:     depc = 0x0000000000000000  perfcnt = 0x0000000000000000
cpu0:   errctl = 0x0000000000000000 cacheerr = 0x0000000000000000
cpu0: tagdatlo = 0x0000000000000000 tagdathi = 0x0000000000000000
cpu0: errorepc = 0x0000000000000000   desave = 0x0000000000000000
GXemul> machine
serial nr: 1
memory: 32 MB
cpu0: RM5200, running
    64-bit Little-endian (MIPS ISA IV), 48 TLB entries
diskimage: nbsd_cobalt.img
    IDE DISK id 0, read/write, 2637 MB (5400864 sectors)
diskimage: simp.tgz
    IDE DISK id 1, read/write, 0 MB (68 sectors)
GXemul> tlbdump
cpu0: (index=0x0 random=0x9 wired=0x1)
  0: vaddr=c00000ffc3f10000 (global):  p0=0x000ff6000 D p1=0x000fc3000 D (4KB)
  1: vaddr=c00000ffc3282000 (global):  p0=0x00119c000 D p1=0x00119b000 D (4KB)
  2: vaddr=c00000ff80004000 (asid 00): p0=(invalid)     p1=(invalid)     (4KB)
  3: vaddr=c00000ff80006000 (asid 00): p0=(invalid)     p1=(invalid)     (4KB)
  4: vaddr=c00000ffc363a000 (global):  p0=0x001f53000 D p1=0x001f52000 D (4KB)
   :
 43: vaddr=c00000ffc3e82000 (global):  p0=0x001c07000 D p1=0x001c5e000 D (4KB)
 44: vaddr=c00000ffc3662000 (global):  p0=0x001f18000 D p1=0x001f17000 D (4KB)
 45: vaddr=c00000ff8005a000 (asid 00): p0=(invalid)     p1=(invalid)     (4KB)
 46: vaddr=c00000ffc3ede000 (global):  p0=0x001abd000 D p1=0x001aa6000 D (4KB)
 47: vaddr=c00000ff8005e000 (asid 00): p0=(invalid)     p1=(invalid)     (4KB)
GXemul> unassemble 0xffc3ede000
000000ffc3ede000: 00000000      nop
000000ffc3ede004: 00000000      nop
000000ffc3ede008: 00000000      nop
000000ffc3ede00c: 00000000      nop
000000ffc3ede010: 00000004      sllv    zr,zr,zr
000000ffc3ede014: 00000004      sllv    zr,zr,zr
000000ffc3ede018: 00000003      sra     zr,zr,0
000000ffc3ede01c: 00586150      mfhi    t4
000000ffc3ede020: 00000000      nop
000000ffc3ede024: 1dcd6503      bgtz    t6,0x000000ffc3ef7434
000000ffc3ede028: 00000000      nop
000000ffc3ede02c: 00000000      nop
000000ffc3ede030: 00000000      nop
000000ffc3ede034: 00000000      nop
000000ffc3ede038: 00000000      nop
000000ffc3ede03c: 00000f02      srl     at,zr,28
000000ffc3ede040: 00000005      special_05      = UNIMPLEMENTED
000000ffc3ede044: 00000003      sra     zr,zr,0
000000ffc3ede048: 00000004      sllv    zr,zr,zr
000000ffc3ede04c: 00000001      special_01      = UNIMPLEMENTED

最後は、loginプロンプトが出てきている時の状態。マシンもお休みしてますな。

GXemul> step 10
<mips_wait_idle>
ffffffff802b2f60: 42000020      wait
<mips_wait_idle>
ffffffff802b2f60: 42000020      wait

だけど、電源事情が厳しき折、これで安心してはいけません。FreeBSD側で動いているGxemulは、 全速力でwait命令をシュミレートしてて、ロードアベレージは、1.0を保ったまま。更に、 FreeBSDのふりをWindows7上で演じてくれている、VMWAREもつられて全速力。タスクマネージャー は、ずっと100%をキープしたままになってます。(GXemulのモニターモードにしとけば、シュミレータも お休みモードになるけど。。。)

あれれ、今気がついたんだけど、親亀の上に子亀がいて、子亀の上に孫亀が居てって構図が いつの間にか出来上がってますなあ。