vak: (Daemon)
За последние три дня я могучим рывком, броском, пинком и нахрапом закончил таки переделку RetroBSD под компилятор Clang. Теперь не нужно бегать искать GCC для mips32. Ставите стандартный Clang и вперёд. Инструкция по сборке лежит в корневом файле README. Для запуска на симуляторе годится обновлённый QEMU для pic32. Если кому понадобится старая версия с GCC - она лежит в бранче gcc.

Поддержку устаревшего хардвера я убрал. Оставил только две платы, обе имеются в продаже:Из минусов: потеряны две фичи.
  • MIPS16e - компактная система команд - не поддерживается компилятором Clang. Формально она там есть, но код генерится совершенно нерабочий. Так что приходится довольствоваться стандартным набором инструкций. Из-за этого некоторые "толстые" приложения не лезут в память, к примеру компилятор SmallerC.
  • Не удаётся собрать библиотеку libc.а в формате a.out для того же компилятора SmallerC. Потому что имеющийся ассемблер mips32 не понимает некоторые навороченные конструкции, порождаемые компилятором Clang. Надо будет допиливать.
Но в целом система фурычит довольно неплохо. Открывается путь для переноса на другие платформы: esp32, stm32, riscv и другие.
vak: (Daemon)
Хотите взглянуть, как грузится RetroBSD с точки зрения последовательности системных вызовов? Стартует /sbin/iuit, из-под него /bin/sh выполняет скрипт /etc/rc, проверяет файловую систему, запускает cron и в конце концов getty. Я сделал флажок в QEMU для pic32, чтобы трассировать системные вызовы. Вывод слегка обработал вручную, вот результат.

gist.github.com/sergev/c0c21f47220e2d3ec6eee4b5b076ec0f
vak: (Daemon)
Внезапно выяснилось, что в RetroBSD была старая ошибка, из-за которой он не запускался на QEMU. Инструкция ERET попадала в delay-слот условного перехода. Строго говоря, это неопределённое поведение. В железе на PIC32 оно работает, но симулятор такого не прощает. Поправил, теперь всё с порядке.
$ qemu-pic32 -machine pic32mx7-max32 -nographic -monitor none -serial stdio -bios boot-max32.hex -kernel unix.hex -sd retrobsd.img
Board: chipKIT Max32
Processor: M4K
RAM size: 128 kbytes
Load file: 'boot-max32.hex', 6720 bytes
Load file: 'unix.hex', 141140 bytes
Card0 image 'retrobsd.img', 102401 kbytes

2.11 BSD Unix for PIC32, revision G512 build 3:
Compiled 2025-02-07 by vak@bumba:
/home/vak/Project/BSD/retrobsd/sys/pic32/max32
cpu: 795F512L 80 MHz, bus 80 MHz
oscillator: HS crystal, PLL div 1:2 mult x20
spi2: pins sdi=RG7/sdo=RG8/sck=RG6
uart1: pins rx=RF2/tx=RF8, interrupts 26/27/28, console
uart2: pins rx=RF4/tx=RF5, interrupts 40/41/42
uart4: pins rx=RD14/tx=RD15, interrupts 67/68/69
sd0: port SPI2, pin cs=RC14
gpio0: portA, pins ii---ii-iiiioiii
gpio1: portB, pins iiiiiiiiiiiiiiii
gpio2: portC, pins i-ii-------iiii-
gpio3: portD, pins --iiiiiiiiiiiiii
gpio4: portE, pins ------iiiiiiiiii
gpio5: portF, pins --ii--------i-ii
gpio6: portG, pins iiii--i-----iiii
adc: 15 channels
pwm: 5 channels
sd0: type I, size 102400 kbytes, speed 10 Mbit/sec
sd0a: partition type b7, sector 2, size 102400 kbytes
sd0b: partition type b8, sector 204802, size 2048 kbytes
sd0c: partition type b7, sector 208898, size 102400 kbytes
phys mem = 128 kbytes
user mem = 96 kbytes
root dev = (0,1)
swap dev = (0,2)
root size = 102400 kbytes
swap size = 2048 kbytes
/dev/sd0a: 1444 files, 12342 used, 89657 free
Starting daemons: update cron

2.11 BSD UNIX (pic32) (console)

login: root
Password:
Welcome to RetroBSD!
erase ^?, kill ^U, intr ^C

# date
Sun Jan 24 23:08:07 PST 2016

# df
Filesystem 1K-blocks Used Avail Capacity Mounted on
/dev/sd0a 101999 12345 89654 12% /

# ps aux
USER PID NICE SZ TTY TIME COMMAND
root 0 0 3 ? 0:00 swapper
root 1 0 35 ? 0:00 init -
root 10 0 7 ? 0:00 update
root 12 0 54 ? 0:00 cron
root 13 0 39 0 0:00 -sh
root 17 0 42 0 0:00 ps aux

# ls /bin
[ crontab hostname pagesize size uucico
adb date id passwd sl uuclean
adc-demo dc iostat pdc sleep uucp
aout dd join picoc smux uudecode
apropos df kill portio sort uuencode
ar diff la pr split uulog
as diskspeed last printenv strip uuname
awk du lcc printf stty uupoll
basename echo lcpp ps su uuq
basic ed ld pwd sum uusend
bc egrep ln pwm sx uusnap
cal emg login ranlib sync uux
calendar env lol rb sysctl uuxqt
cat expr ls re sz vi
cb false mail renice tail vmstat
cc fgrep make renumber tar w
chat-server file man retroforth tee wall
chflags find md5 rev telnet wc
chfn fold med rm test web-client
chgrp forth mesg rmail time web-server
chmod fstat mkdir rmdir tip whatis
chpass glcdtest more rx touch whereis
chsh globdump msec rz tr who
cmp globread mv sb true whoami
col globwrite nice scc tsort write
comm grep nm scm tty xargs
compress groups nohup sed uname zcat
cp head ntpdate setty uncompress
cpp hostid od sh uniq

# cd /share/examples/asm
# make clean
rm -f *.o ashello echo *.dis *~

# cat ashello.S
/*
* This is an example of MIPS assembly program for RetroBSD.
*
* To compile this program, type:
* cc -c ashello.S
* ld ashello.o -o ashello
*/
#include <syscall.h>

.data // begin data segment
hello: .ascii "Hello, assembly world!\n" // a string

.text // begin code segment
.globl start // entry point for ld
start:
li $a0, 0 // arg 1: stdout fd
la $a1, hello // arg 2: string address
li $a2, 23 // arg 3: string length
syscall SYS_write // call the kernel: write()
nop // returns here on error
nop // skips two words on success

li $a0, 0 // arg 1: exit status
syscall SYS_exit // call the kernel: exit()
// no return

# make ashello
cc -c ashello.S
ld ashello.o -o ashello

# ./ashello
Hello, assembly world!

# cd /share/examples/c
# make clean
rm -f *.o *~ hello stdarg skeleton primelist primesum test1 test2 test3 gpio adc rain q8 tetris lcd6

# cat hello.c
#include <stdio.h>

int main()
{
printf ("Hello, C World!\n");
return 0;
}

# make hello
cc -o hello hello.c

# ./hello
Hello, C World!

# halt
killing processes... done
syncing disks... done
halted
Обратите внимание: работают ассемблер и Си компилятор.
vak: (Default)
Один крутой японец написал живопырку операционной системы для процессора RISC-V, уложившись в 1000 строк кода. Давайте глянем.
$ git clone https://github.com/nuta/operating-system-in-1000-lines.git
$ cd operating-system-in-1000-lines
$ wc *.c *.h
96 252 2321 common.c
576 1985 17559 kernel.c
38 113 1092 shell.c
47 134 1160 user.c
33 120 994 common.h
178 459 4745 kernel.h
14 39 294 user.h
982 3102 28165 total
Скомпилируем и запустим на симуляторе. Предварительно надо в файле run.sh настроить пути к clang и llvm-objcopy.
$ brew install llvm lld qemu
$ ./run.sh
+ QEMU=qemu-system-riscv32
+ CC=/usr/local/Cellar/llvm/19.1.6/bin/clang
+ OBJCOPY=/usr/local/Cellar/llvm/19.1.6/bin/llvm-objcopy
+ CFLAGS='-std=c11 -O2 -g3 -Wall -Wextra --target=riscv32 -ffreestanding -nostdlib'
+ /usr/local/Cellar/llvm/19.1.6/bin/clang -std=c11 -O2 -g3 -Wall -Wextra --target=riscv32 -ffreestanding -nostdlib -Wl,-Tuser.ld -Wl,-Map=shell.map -o shell.elf shell.c user.c common.c
+ /usr/local/Cellar/llvm/19.1.6/bin/llvm-objcopy --set-section-flags .bss=alloc,contents -O binary shell.elf shell.bin
+ /usr/local/Cellar/llvm/19.1.6/bin/llvm-objcopy -Ibinary -Oelf32-littleriscv shell.bin shell.bin.o
+ /usr/local/Cellar/llvm/19.1.6/bin/clang -std=c11 -O2 -g3 -Wall -Wextra --target=riscv32 -ffreestanding -nostdlib -Wl,-Tkernel.ld -Wl,-Map=kernel.map -o kernel.elf kernel.c common.c shell.bin.o
+ cd disk
+ tar cf ../disk.tar --format=ustar hello.txt meow.txt
+ qemu-system-riscv32 -machine virt -bios default -nographic -serial mon:stdio --no-reboot -d unimp,guest_errors,int,cpu_reset -D qemu.log -drive id=drive0,file=disk.tar,format=raw,if=none -device virtio-blk-device,drive=drive0,bus=virtio-mmio-bus.0 -kernel kernel.elf

OpenSBI v1.5.1
____ _____ ____ _____
/ __ \ / ____| _ \_ _|
| | | |_ __ ___ _ __ | (___ | |_) || |
| | | | '_ \ / _ \ '_ \ \___ \| _ < | |
| |__| | |_) | __/ | | |____) | |_) || |_
\____/| .__/ \___|_| |_|_____/|____/_____|
| |
|_|

Platform Name : riscv-virtio,qemu
Platform Features : medeleg
Platform HART Count : 1
Platform IPI Device : aclint-mswi
Platform Timer Device : aclint-mtimer @ 10000000Hz
Platform Console Device : uart8250
Platform HSM Device : ---
Platform PMU Device : ---
Platform Reboot Device : syscon-reboot
Platform Shutdown Device : syscon-poweroff
Platform Suspend Device : ---
Platform CPPC Device : ---
Firmware Base : 0x80000000
Firmware Size : 319 KB
Firmware RW Offset : 0x40000
Firmware RW Size : 63 KB
Firmware Heap Offset : 0x47000
Firmware Heap Size : 35 KB (total), 2 KB (reserved), 10 KB (used), 22 KB (free)
Firmware Scratch Size : 4096 B (total), 244 B (used), 3852 B (free)
Runtime SBI Version : 2.0

Domain0 Name : root
Domain0 Boot HART : 0
Domain0 HARTs : 0*
Domain0 Region00 : 0x00100000-0x00100fff M: (I,R,W) S/U: (R,W)
Domain0 Region01 : 0x10000000-0x10000fff M: (I,R,W) S/U: (R,W)
Domain0 Region02 : 0x02000000-0x0200ffff M: (I,R,W) S/U: ()
Domain0 Region03 : 0x80040000-0x8004ffff M: (R,W) S/U: ()
Domain0 Region04 : 0x80000000-0x8003ffff M: (R,X) S/U: ()
Domain0 Region05 : 0x0c400000-0x0c5fffff M: (I,R,W) S/U: (R,W)
Domain0 Region06 : 0x0c000000-0x0c3fffff M: (I,R,W) S/U: (R,W)
Domain0 Region07 : 0x00000000-0xffffffff M: () S/U: (R,W,X)
Domain0 Next Address : 0x80200000
Domain0 Next Arg1 : 0x87e00000
Domain0 Next Mode : S-mode
Domain0 SysReset : yes
Domain0 SysSuspend : yes

Boot HART ID : 0
Boot HART Domain : root
Boot HART Priv Version : v1.12
Boot HART Base ISA : rv32imafdch
Boot HART ISA Extensions : sstc,zicntr,zihpm,zicboz,zicbom,sdtrig,svadu
Boot HART PMP Count : 16
Boot HART PMP Granularity : 2 bits
Boot HART PMP Address Bits: 32
Boot HART MHPM Info : 16 (0x0007fff8)
Boot HART Debug Triggers : 2 triggers
Boot HART MIDELEG : 0x00001666
Boot HART MEDELEG : 0x00f0b509

virtio-blk: capacity is 3072 bytes
file: hello.txt, size=83
file: meow.txt, size=6
> _
Ядро стартовало, и мы видим приглашение для ввода команды. Примитивный шелл распознаёт только hello, readfile, writefile и exit.
> hello
Hello world from shell!

> readfile
Can you see me? Ah, there you are! You've unlocked the achievement "Virtio Newbie!"

> writefile
wrote 2560 bytes to disk

> readfile
Hello from shell!

> exit
process 2 exited
PANIC: kernel.c:564: switched to idle process
Ничо так, прикольно. Полная история на английском здесь: Operating System in 1,000 Lines. На самом деле чувак просто научился переключаться между режимом ядра и режимом юзера.
vak: (Знайка)
Набрёл на статью: "SvarDOS: DR-DOS is reborn as an open source operating system". Поигрался маленько.

"SvarDOS — это проект с открытым исходным кодом, призванный интегрировать лучшее из имеющихся в настоящее время инструментов, драйверов и игр DOS. Разработка DOS была заброшена коммерческими игроками давно, в основном в начале девяностых. В настоящее время он выживает исключительно благодаря усилиям любителей и ретро-энтузиастов, но это крайне разреженная и неорганизованная экосистема. SvarDOS стремится собрать доступное программное обеспечение DOS и упростить поиск и установку приложений с помощью сетевого менеджера пакетов (вроде apt-get, но для DOS и способного работать на ПК 8086)."

Вот образ диска с предустановленной системой. Скачиваем, запускаем:
wget https://pub.sergev.org/dos/svardos.qcow.xz
xz -d svardos.qcow.xz
qemu-system-i386 -m 64 -hda svardos.qcow

Такой себе DOS получается. Смотрим содержимое диска C, версию.

Можно скачивать и ставить всякий дополнительный софт из сети. Но надо сетевой (пакетный) драйвер запустить сначала. Я не стал разбираться.

Чтобы установить систему с нуля, надо скачать и загрузиться с CD-ROM:
wget http://svardos.org/repo/sv-repo.iso
qemu-img create -f qcow2 svardos.qcow 2G
qemu-system-i386 -m 64 -hda svardos.qcow -cdrom sv-repo.iso -boot d
Дальше следуем инструкциям по установке.
vak: (Default)
Вы заметили, что все операционные системы нынче стали 64-битными. Windows и мак уже давно, а теперь и Линуксы следом. Ubuntu нынче поддерживает только 64-битные архитектуры: amd64, arm64, ppc64, riscv64, s390x. Куда бежать, если для разработки вдруг понадобился 32-битный Линукс? Есть выход, однако: Debian всё ещё имеет версии для i386, arm32 (armel и armhf) и mips32. Их нетрудно установить под симулятором QEMU. Поскольку i386 и mips32 сходят со сцены, покажу на примере архитектуры armhf.

(1) Устанавливаем симулятор QEMU: на маке это команда "brew install qemu", на Линуксе "sudo apt install qemu-system-arm".

(2) Скачиваем файлы с сайта Debian.
wget https://ftp.debian.org/debian/dists/Debian12.8/main/installer-armhf/current/images/netboot/vmlinuz
wget https://ftp.debian.org/debian/dists/Debian12.8/main/installer-armhf/current/images/netboot/initrd.gz
(3) Создаём образ диска с запасом по размеру.
qemu-img create -f qcow2 rootfs.qcow 16G
(4) Запускаем установщик.
qemu-system-arm \
-nographic \
-machine virt \
-m 2G \
-smp 4 \
-device virtio-blk-device,drive=disk \
-drive file=rootfs.qcow,if=none,id=disk \
-device virtio-net-device,netdev=net \
-netdev user,id=net,hostfwd=tcp::2222-:22 \
-kernel vmlinuz \
-initrd initrd.gz \
-append "ip=dhcp, console=ttyAMA0"
(5) В установщике выполняем всё, что требуется. Процесс занимает некоторое время. Получим образ диска с Линуксом размером 1.7 Гбайт.

(вместо 2-5) Можно не мучиться и сразу скачать готовые файлы. Распаковать командой xz:
wget https://pub.sergev.org/unix/debian-on-armhf/rootfs.qcow.xz
wget https://pub.sergev.org/unix/debian-on-armhf/vmlinuz-6.1.0-27-armmp-lpae
wget https://pub.sergev.org/unix/debian-on-armhf/initrd.img-6.1.0-27-armmp-lpae
xz -v -d rootfs.qcow.xz
(6) Запускаем Линукс:
qemu-system-arm \
-nographic \
-machine virt \
-m 2G \
-smp 4 \
-device virtio-blk-device,drive=disk \
-drive file=rootfs.qcow,if=none,id=disk \
-device virtio-net-device,netdev=net \
-netdev user,id=net,hostfwd=tcp::2222-:22 \
-kernel vmlinuz-6.1.0-27-armmp-lpae \
-initrd initrd.img-6.1.0-27-armmp-lpae \
-append "ip=dhcp console=ttyAMA0"
(7) Входим как root, пароль debian. Или как debian, пароль тоже debian. Остановить систему можно командой poweroff. Создать нового юзера можно командой adduser.

Обычный юзер может входить по сети, через локальный порт 2222:
ssh -p 2222 user@localhost
vak: (Daemon)
Я уже рассказывал про утилиту UTM и запуск виртуального Линукса на маке. Оказывается, с её помощью можно гонять и разные непривычные архитектуры. К примеру, нетрудно запустить Солярис на SPARC. Готовая конфигурация скачивается прямо с официального сайта UTM:



Стартуем, вводим "book disk0" для загрузки с диска.



+4 )
vak: (Default)
Оказывается, ядро MacOS для arm64 можно запустить на интеловском компьютере с помощью QEMU. Не знаю зачем, но прикольно. Вот тут подробности:

github.com/cylance/macos-arm64-emulation
vak: (Default)
Некие крутые перцы умудрились вытащить из загашников, отряхнуть пыль и установить на QEMU операционную систему FreeBSD версии 1.0. Это 1993 год, приятно вспомнить. Я тогда много занимался этой операционкой: драйверы, русификация, сетевые протоколы.

Скачиваем образ диска: FreeBSD-1.0_HDA.img

Запускаем:
qemu-system-i386 -monitor stdio \
-vga cirrus \
-m 128 \
-rtc base=localtime \
-hda FreeBSD-1.0_HDA.img \
-boot c \
-net nic,model=ne2k_isa \
-net tap,ifname=tap0,script=no,downscript=no \
-name "FreeBSD 1.0"
Приглашение вторичного загрузчика:

Начало загрузки ядра: копирайты, разпознавание устройств писишки. Больше 64 мегабайт памяти ядро не понимает. Шина ISA: тогда PCI ещё не было.

Загрузились, вводим имя юзера.

Смотрим версию ядра, размеры файловых систем, версию компилятора.
vak: (Default)
Раз уж с Xenix 8086 неплохо получилось, решил я заодно и с Xenix 286 разобраться. Как выяснилось, IBM PC AT с достаточной степенью достоверности имитируется стандартным симулятором QEMU. Запускается командой:
qemu-system-i386 -L pc-bios -m 16 -hda xenix286.img
Система стартует на ура:

Образ диска xenix286.img с предустановленной операционкой и всеми пакетами можно скачать по ссылке: xenix286-virgin.zip

Сам QEMU ставится обычным образом: на маке "brew install qemu", на убунту "sudo apt-get install qemu-system-x86".
vak: (Default)
Мне удалось таки поставить Xenix 8086 на симуляторе. Вот так выглядит загрузка на pce-ibmpc:

Ставил я по этой инструкции. Там есть одна ошибка: количество цилиндров на диске указано как 613, а надо 615. Иначе система установится, но после проверки файловой системы рано или поздно начнёт выдавать ошибки обмена с диском.

Использовал симулятор MIME. Он тривиально ставится на маке командой "brew install mime rom-tools". Ну и скачать бинарники BIOS по ссылке: https://wowroms.com/en/roms/mame/ibm-pc-5150/85150.html

Хитрость в том, что диск надо форматировать в фиксированной геометрии, иначе ничего не получится:
chdman createhd -o xenix8086.chd -chs 615,4,17
После этого установка запускается командой:
mame ibm5150 -floppydisk1 N1.img -w -nothrottle -verbose
Готовый образ диска после установки, в форматах CHD (сжатый для MIME) и IMG (сырой), можно скачать отсюда: xenix8086-virgin.zip

Чтобы запустить Xenix 8086 с этого образа диска на симуляторе PCE, годится вот эта конфигурация: pce-xenix8086.cfg
vak: (Default)
Появилась версия симулятора QEMU с поддержкой архитектуры Эльбрус-2000.

Исходники здесь: https://git.mentality.rip/OpenE2K/qemu-e2k
vak: (Default)
Я уже писал, как за два простых шага установить и запустить Debian на плате pic32mz-da. Компиляцию U-Boot для микроконтроллера pic32 я тоже описывал. Здесь я покажу, как собрать из исходников ядро Linux, и как с нуля построить образ файловой системы Debian на карточке micro-SD.

1. Строим ядро Linux для pic32

Исходные тексты ядра Linux для микроконтроллеров семейства pic32mz-da были опубликованы фирмой Microchip а 2015 году. Я внес два небольших исправления: доработал драйвер SDHC, чтобы обойти багу с короткими обменами (описанную в Errata sheet), и добавил флаги в ядре, нужные для корректного функционирования systemd.

Вот как выглядит компиляция под Ubuntu версии 18.04. Огромное спасибо Мите Коротину, который первым прошёл этот трудный путь и показал мне все хитрости. Устанавливаем кросс-компилятор:
sudo apt-get install gcc-mips-linux-gnu
Скачиваем тексты ядра Linux, с правками для PIC32:
git clone https://github.com/sergev/linux-pic32.git
Конфигурируем и собираем. Здесь я предполагаю, что в каталоге u-boot-pic32 находится U-Boot, готовый и собранный для pic32. Нам от него понадобится утилита mkimage:
cd linux-pic32
make ARCH=mips CROSS_COMPILE=mips-linux-gnu- pic32mzda_defconfig
make ARCH=mips CROSS_COMPILE=mips-linux-gnu-
gzip -9 < arch/mips/boot/vmlinux.bin > arch/mips/boot/vmlinux.bin.gz
../u-boot-pic32/tools/mkimage -A MIPS -a 0x88000000 -e 0x88000400 -d arch/mips/boot/vmlinux.bin.gz arch/mips/boot/vmlinux-pic32
mkdir -p ../boot
cp -a arch/mips/boot/uImage ../boot/vmlinux-pic32
cp -a arch/mips/boot/dts/pic32/pic32mzda_sk.dtb ../boot/pic32mzda.dtb
В результате мы имеем в папке boot бинарное ядро и дерево устройств, которое надо будет поместить в папку /boot файловой системы на SD-карточке.

Собираем загружаемые модули:
make ARCH=mips CROSS_COMPILE=mips-linux-gnu- INSTALL_MOD_PATH=$PWD/.. modules_install
Содержимое папки lib/modules/ надо будет скопировать в /lib/modules на SD-карточке.

2. Собираем файловую систему Debian для mips32

vak: (Default)
Процедура установки: debian-mips64el-on-qemu

Протокол загрузки и информация об аппаратной конфигурации: protocol-debian-mips64el

Дерево устройств: device-tree-mips64el-on-qemu
vak: (Улыбка)
В блоге neozeed появилась статья про запуск LiteBSD на QEMU под Windows.



Скачать готовый бинарный пакет можно по ссылке: qemu-2.3.5_win32_MIPS_LiteBSD.7z

Подсказывают, что в пакете еще парочки файлов не хватает:
http://qemu.weilnetz.de/w32/dll/libgcc_s_sjlj-1.dll
http://qemu.weilnetz.de/w32/dll/libssp-0.dll
vak: (Улыбка)
Сварганил на досуге забавную штуку: вариант симулятора QEMU для микроконтролеров Microchip PIC32. Инструкцию по сборке и примеры запуска можно посмотреть здесь: https://github.com/sergev/qemu/wiki

Симулятор реализует две архитектуры: pic32mx7 и pic32mz. Для каждой из архитектур поддерживается несколько разных плат. Весь список на сегодняшний день:Примеры запуска реальных приложений:
"Hello World" на плате Max32
2.11BSD на плате Max32
4.4BSD на плате WiFire
vak: (Улыбка)
Почти удалось убедить руководство, что QEMU не самый лучший в мире симулятор. Заняло всего полгода. Может быть, получится сэкономить на этом пару человеко-лет мартышкиного труда.
vak: (Default)
QEMU известен как эмулятор компьютеров с различной архитектурой: i386, ARM, MIPS, PowerPC, SPARC. Его ценят за то, что он очень "быстрый". На мало кто знает, что суть QEMU в другом: это "бинарный транслятор". Он делит бинарный код эмулируемой программы на линейные участки - "блоки", разделённые командами переходов. Каждый блок транслируется в систему команд хост-процессора. Затем полученный код выполняется.

Для архитектуры MIPS эмулятор QEMU поддерживает четыре платформы: MIPS Jazz, MIPS Malta, MIPSsim и MIPS 4k (коротенький обзор здесь). Две первые - реальные компьютеры, две вторые - виртуальные системы. Я сделал простейший пример типа "Hello World" для запуска на платформе MIPS 4k. Исходники, бинарники и скрипты запуска можно взять здесь. Запуск эмулятора делается командой "qemu-system-mipsel -M mips -L . -bios hello.bin".

Дизассемблированный код программы находится в файле hello.dis. В файле протокола qemu.log можно посмотреть, как QEMU делит код на блоки и транслирует в команды i386. Метками "IN:" помечены блоки кода MIPS, метками "OP:" - операции виртуальной машины, полученные из исходного кода. Метки "OUT:" - готовый к выполнению код i386.

Всего в программе было 113 команд MIPS. После трансляции образовалось 894 команды i386. Делаем грубую оценку: при запуске QEMU на Pentium 3 ГГц скорость выполнения будет соответствовать процессору MIPS с частотой 3*113/894 = 380 МГц.