跳轉到內容

Aros/平臺/68k 支援/開發人員/編譯器

來自華夏公益教科書
Aros 華夏公益教科書的導航欄
Aros 使用者
Aros 使用者文件
Aros 使用者常見問題解答
Aros 使用者應用程式
Aros 使用者 DOS Shell
Aros/使用者/AmigaLegacy
Aros 開發文件
Aros 開發人員文件
從 AmigaOS/SDL 移植軟體
Zune 初學者指南
Zune .MUI 類
SDL 初學者指南
Aros 開發人員構建系統
特定平臺
Aros x86 完整系統 HCL
Aros x86 音訊/影片支援
Aros x86 網路支援
Aros Intel AMD x86 安裝
Aros 儲存支援 IDE SATA 等
Aros Poseidon USB 支援
x86-64 支援
摩托羅拉 68k Amiga 支援
Linux 和 FreeBSD 支援
Windows Mingw 和 MacOSX 支援
Android 支援
Arm Raspberry Pi 支援
PPC Power Architecture
雜項
Aros 公共許可證


交叉編譯器

[編輯 | 編輯原始碼]

從 AROS 和 AROS-contrib 樹為 i386 構建需要很長時間,並且通常需要相當新的軟體版本,並且試圖在緩慢的模擬下使用過時的構建工具版本或在真實的 m68k 硬體上構建,不會讓工作變得更容易。

更有意義的是,在 GNU-Linux 或 FreeBSD 或 Windows 下建立一個 gnu m68k-amiga 交叉編譯環境,然後嘗試為 m68k-amiga 目標構建 AROS。將檔案傳輸過去並測試與 UAE 或 amiga-forever 的相容性。建議建立一個 68k-Linux 託管的 AROS,並在 Aranym 中對其進行測試。這樣,您就不必擔心一開始的定製晶片。您不需要編寫任何新的驅動程式;為其他 Linux 託管的 AROS 風格的現有驅動程式應該可以正常工作。

這裡,如果您刪除了這個完整檔案以及我釋出的連結中的 g++ 檔案,那麼 G++ 應該可以使用 c++ 庫進行構建。

--enable-languages=c


Download latest Ubuntu image.

Start vmware, let it install using automatic installation, everything is done automatically, when it is ready, it boots directly to desktop. Select synaptics package manager from admin menu, select and install all packages I listed...

Packages needed:

binutils-source
libcloog-ppl-dev (adds lots of other dependencies)
g++
libelf-dev
bison
flex
gcc-4.5-source
libmpfr-dev
libmpc-dev
libecm-dev
netpbm

mkdir dev
cd dev
mkdir binutils
cd binutils
tar xvfJ /usr/src/binutils/binutils-2.20.51.tar.xz
binutils-2.20.51/configure --prefix=/opt/m68k-elf --target=m68k-elf
make -j2
sudo -s
make install
exit
cd ..
mkdir gcc
cd gcc
tar xvfJ /usr/src/gcc-4.5/gcc-4.5.1.tar.xz
cd gcc-4.5.1
patch -p1 <path>/0001-m68k-amiga-Amiga-ABI-support.patch
cd ..
gcc-4.5.1/configure --without-headers --disable-threads --disable-libssp
--disable-nls --disable-shared --without-pic --prefix=/opt/m68k-elf
--target=m68k-elf --enable-languages=c
make -j2
sudo -s
make install
exit

然後按照我的指南操作。只需要大約 30 分鐘。

add PATH=$PATH:/opt/m68k-elf/bin to ~.bashrc


我在 12.10 上嘗試自己構建,並且成功了。這是我的配置行

CC=gcc-4.6 /home/weissms/aros/aros-src/configure --target=amiga-m68k --enable-ccache --with-portssources=~/aros/Sources --with-aros-toolchain-install=/home/weissms/media/data/aros/build/crosstools/

m68k-amiga-aros-ar 是一個指向 /home/weissms/media/data/aros/build/crosstools/m68k-aros-ar 的連結。


在我的 VirtualBox Linux 機器上構建了大約 4 個小時後,它最終中止並出現以下錯誤:確保您的樹是最新的。該檔案幾天前損壞。(r46006)順便說一句,沒有必要編譯所有內容,可啟動設定只需要 workbench 和 kernel-link-amiga-m68k 目標。據我所知,非 m68k 驅動程式沒有被停用,因為沒有人費心去停用它們,而且至少在理論上,大多數驅動程式可以透過 Amiga Zorro PCI 橋工作。當然,英特爾 GMA 不行 :)


有人嘗試為 68k 製作 g++ 交叉編譯器嗎?或者,也許有更簡單的方法來為 Aros 68k 編譯 owb?這是 Fab 的 Odyssey。構建沒有與 AROS 構建系統耦合。它確實需要 cmake,以及一些預設情況下不在 contrib 中構建的庫。(並且它在 3GHz 機器上使用 -j 3 構建需要 1 個小時。)



我為 MegaDrive 製作了一個 680x0 交叉編譯器(它還包含一個 SH2 交叉編譯器,但這很容易被剪掉)。它是 4.5.2 的通用構建,但是,它可能沒有所需的標誌。以下是版本資訊

Target: m68k-elf
Configured with: ../gcc-4.5.2/configure --target=m68k-elf
--prefix=/opt/toolchains/gen/m68k-elf --without-headers --with-newlib
--enable-languages=c --disable-libssp --disable-tls --with-cpu=m68000
: (reconfigured) ../gcc-4.5.2/configure --target=m68k-elf
--prefix=/opt/toolchains/gen/m68k-elf --without-headers --with-newlib
--enable-languages=c --disable-libssp --disable-tls --with-cpu=m68000
: (reconfigured) ../gcc-4.5.2/configure --target=m68k-elf
--prefix=/opt/toolchains/gen/m68k-elf --with-newlib --disable-libssp
--disable-tls --enable-threads=single
--enable-languages=c,c++,objc,obj-c++ --with-cpu=m68000
Thread model: single
gcc version 4.5.2 (GCC)

請注意諸如執行緒模型、停用的執行緒本地儲存等內容。這些需要在構建工具鏈的 makefile 中更改。我在 GenDev GenDev 用於構建工具鏈的過程和檔案。

它可以很容易地進行更改以適應 AROS 所需的任何標誌,以及不同的預設目標 CPU(當前設定為 68000)。



使用 svn 獲取最新樹。

cd ~
mkdir build
cd build

(It is very important to have separate build tree, do not compile inside source tree)

 ../AROS/configure --target=amiga-m68k --with-optimization="-Os" --with-serial-debug --disable-mmu 
(do not change optimization setting, it is not going to work) 
 make
(wait until you get some error, it is some package that is not yet m68k compatible, not important) 

 make kernel-link-amiga-m68k

rom images are now in distfiles

make workbench to create full wb setup

嗯。看起來您的交叉編譯器不允許 .text 對齊。您使用的是哪個版本的 m68k gcc?如果您使用了 arch/m68k-amiga/doc/build-toolchain.sh 指令碼,那麼您應該使用這個版本

$ m68k-elf-gcc -v
Using built-in specs.
COLLECT_GCC=m68k-elf-gcc
COLLECT_LTO_WRAPPER=/opt/m68k-elf/libexec/gcc/m68k-elf/4.5.1/lto-wrapper
Target: m68k-elf
Configured with: ../configure --without-headers --disable-threads --disable-libssp --disable-nls --disable-shared --without-pic --prefix=/opt/m68k-elf --target=m68k-elf --program-prefix=m68k-elf- --enable-languages=c
Thread model: single
gcc version 4.5.1 (GCC)

i386 和 x86_64 構建使用一個“偽交叉編譯器”(主機的 gcc + 配置)。我認為您應該看看 mingw32 埠是如何構建的 - 它使用真實的、預構建的交叉編譯器來完成整個鏈(就我所知,向 Pavel Fedin 諮詢更多資訊)。如果您遵循這種方法,我們甚至可以在 VPS 上為您的埠設定每日構建 - 我認為這對於避免在 m68k 上引入由處理其他埠的人員引入的迴歸非常重要。

如果很多東西被新增到“通用”目標(例如 linklibs),然後透過同一個目標使用,這會導致當您嘗試使用特定目標時,大量無關的東西被構建。我認為(IMHO)如果這些目標只用於分組主要系統物件,而不僅僅是所有物件,並且 mmakefile 正確地使用它們實際使用的模組的依賴專案標,那就太好了。

目標應該是擺脫所有包含和 linklibs 作為元依賴項,而不是擴充套件它們。

Core-linklibs 是 gcc 預設新增的 linklibs 的元目標。使用某些 linklibs 的程式需要在其 mmakefile 中明確提供正確的依賴項。

這是我的 binutils 的“strip”,它消除了 .rela.text 和 .rela.rodata(大小為零)。據我所知,我們不應該在 AROS 二進位制檔案上使用 strip 作為單獨的命令。但是,我們可以將 -s 新增到連結器的命令列中。不要明確使用 strip,因為它會刪除某些符號,而這些符號對於 AROS 程式正常工作是必需的。

--strip-unneeded --remove-section .comment 

沒問題,但是純“strip”會建立損壞的二進位制檔案。

我不得不將 Graphics/*LayerRom 系列更改為使用 A4 而不是 A5,因為 GCC 似乎認為 A5 幀指標是不可變的。"-fomit-frame-pointer -fcall-saved-reg-a5" 選項怎麼樣?您可以在層跳轉表中新增一個醜陋的包裝器,以切換暫存器嗎?(類似於 Disable() 及其朋友)這是否也導致了無法解釋的引導選單崩潰?

但是

  • GCC 將 -fomit-frame-pointer 視為提示,而不是要求。GCC 中的 reload1.c 演算法可以強制使用幀指標,而不管“omit-frame-pointer”設定如何。
  • GCC 當幀指標 (%a5) 在使用中時,由於上述解釋,我得到以下錯誤
cc1: error: can't use 'a5' as a call-saved register

最大的問題不是這個問題的普遍性,而是這個問題的*稀有性*。如果這是一個*嚴重*問題,那麼我可以忍受它並處理會導致巨大膨脹的更改。

就目前而言,以下是在 AROS 中的所有呼叫(在 *.conf 檔案中定義),這些呼叫可能存在問題,這意味著我無法證明巨大的膨脹

rom/exec/exec.conf:
    ULONG Supervisor(ULONG_FUNC userFunction) (A5)
rom/expansion/
    UCF5 calls to the ROM diagPoint
rom/dos/

rom/graphics/graphics.conf:
    void LockLayerRom(struct Layer *l) (A5)
    void UnlockLayerRom(struct Layer *l) (A5)
    BOOL AttemptLockLayerRom(struct Layer *l) (A5)

workbench/libs/popupmenu/popupmenu.conf:
    APTR PM_OBSOLETEFilterIMsgA(struct Window *window, struct
PopupMenu *pm, struct IntuiMessage *im, struct TagItem *tags) (A1, A2, A3, A5)

workbench/libs/datatypes/datatypes.conf:
    ULONG DoDTDomainA(Object *o, struct Window *win, struct Requester
*req, struct RastPort *rport, ULONG which, struct IBox *domain, struct TagItem *attrs) (A0, A1, A2, A3, D0, A4, A5)

我有一些想法,但它們都有缺點

  • 為所有庫函式建立一個堆疊引數包裝器,然後透過 jsr NN(%a6) 呼叫真正的暫存器呼叫函式。
+ In this model, the AROS_LH* macros generate _Exec_Foo (stackcall) wrappers for Exec_Foo (regcall). AROS_LC* macros would call the _Exec_Foo stackcall wrappers 
+ AmigaOS 3.x apps would work unchanged against the ROM
- Unneccessary bloat for the ROM. This bloats all calls in the ROM to fix only 10 calls. 
- Only works for the ROM. Things get out of hand and messy for building the AROS user-space libraries and apps. 
  • 為每個使用 A4 而不是 A5 的受影響的 libcalls 建立一個額外的庫呼叫(即 Exec/Supervisor_A4),並修復呼叫者以便在他們的標頭檔案中有一個“#define Supervisor Supervisor_A4”。然後為每個函式定義一個 asm 存根,該存根儲存 A5 並將 A4 移動到 A5 中,呼叫真正的例程,

然後恢復 A5。

+ Relatively low impact, only affects the problem APIs
+ Will work with existing AmigaOS 3.x apps
+ No problems with compiling AROS apps
- May have to get genmodule in the act to get this to work cleanly.
- Will *permanently* affect the AROS ABI for m68k, and consume library call slots for *ALL OTHER ARCHITECTURES*.


  • 修復 gcc 以在它認為“強制”使用幀指標時給出診斷資訊,這些診斷資訊足以讓程式設計師做出正確的更改,以便 gcc 不會在該例程中生成幀指標。
- This code is very convoluted and ugly. I tried this once, and ran away screaming.
  • 修復 gcc 使其永遠不需要在 m68k 上使用幀指標。
  - This may be impossible. reload1.c is an impenetrable morass of evil.
  • 修復 gcc 使其能夠識別何時 FP 將被覆蓋,並將 FP 移動到一個備用暫存器。

+ 將是一個極好的修復,並且應該可以移植到其他架構。- 看起來這可能是一項巨大的任務,或者至少是一項超出我技能範圍的任務。


  • 為 LLVM 建立一個 M68K 目標後端
- Would distract from the AROS KS Phase I task for at least a month. 
- May run into intractable issues (fixed ABI definition per arch?, impossible to debug LLVM code generation issues?, etc)
+ HUGE long term benefits if we get it to work!



GCC 2.95.3

[編輯 | 編輯原始碼]
  • gcc 2.95 已經過時了 - AROS 在編譯和連結時使用了許多 GCC 3.x 或更高版本的特性。
  • gcc 2.95 程式碼生成在 m68k 上非常臃腫 - 比 gcc 4.5.1 還要糟糕得多。例如,使用我的暫存器呼叫(損壞)內聯駭客的 4.5.1 上的 400K ROM 文字空間在 gcc 2.95 上膨脹到了 1.2M。不能接受!- 最糟糕的情況之一是 Exec/Forbid - 它從 2 條指令膨脹到了 35 條!

我本來希望避免的程式碼生成錯誤 - 它顯然很古老,因為 2.95.3 在相同的位置仍然生成相同的錯誤。(由於某些極端情況下的最佳化問題,它使用 lea %sp(#n),%a3 而不是 move.l %sp(#n),%a3)。所以,我現在要做的就是專注於 2.95.3 程式碼最佳化錯誤(不幸的是,它出現在 PrepareExecBase 中),修復它,然後將該補丁移植到 gcc 4.5.1。它是 -fpic 最佳化,它被暫存器使用破壞了。-fno-pic 現在暫時解決了這個錯誤,但我需要在我需要製作“真正的”PIC 庫時重新調查這個問題。

GCC 2.95(可能不是所有版本,但 IIRC 2.95.3 做到了)可以為像這樣的 vararg 宏生成錯誤的程式碼

#define OpenWindowTags(arg1, ...) \
({ \
    IPTR __args[] = { AROS_PP_VARIADIC_CAST2IPTR(__VA_ARGS__) }; \
    OpenWindowTagList((arg1), (struct TagItem *)__args); \
})

在 x86 和 68k 上。IIRC 這是切換到 gcc 3 的原因之一。

這是來自 binutils 彙編器的。要查詢錯誤,可以使用一個開關,即臨時檔案不會被刪除。

要避免啟動程式碼,連結器選項

nostarfiles 
noixemul

GCC 3.4 太過破損,無法用最佳化器編譯 ffmpeg。ffmpeg 使用 GCC 4.5.0(不是 AROS 版本)構建。但可以很好地用 GCC 4.3.2 編譯(在 GCC 4.5 釋出之前使用過)。

這裡只有 cygwin 託管的 GCC 4.3.2 和 GCC 4.50。使用這些編譯器,許多 amiga 埠可以編譯

在這些編譯器上還有一個文字檔案說明如何構建 GCC。68k GCC 在 GCC 中得到官方支援。因此,為您的喜歡的 Linux 編譯 GCC 很容易。

我建議使用來自 includes 或 ixemul 的新的 math-68881.h。這是專門修改以與更新的編譯器一起工作。GCC 的問題是在 asm 行之後的更新編譯器中,需要新增 \n\t。但更新的 asm 程式碼已經包含了這個。

我認為在這個 AROS 構建中最佳化器被關閉了。預設的 GCC 僅建立 68000 程式碼。

我不知道他們如何在僅 3.1 級啟動盤中容納所有東西,而不使用 4000T 使用的技巧,比如將 Workbench.library 移到磁碟。在這種情況下,編譯後的 C 程式碼幾乎都會更大。AmigaOS 3.1 的大部分是用 C 編寫的。dos.library 在 1.3 之前是用 BCPL 編寫的,並在 2.0(甚至 1.4 beta?)時被轉換為 C。 IIRC,他們使用了多個編譯器,其中一個是 Lattice。後來變成了 SAS/C。在 gcc 2.95 時代,我做了一些基準測試,我嘗試過的軟體在 gcc 上比在 SAS/C 上更快。許多因素會影響 AROS68K 的執行速度和大小。現在談論它將是什麼樣子還為時過早。



由於使用了 compiler/include/asm.c 中的慣用法,我們似乎已經將自己鎖定在 GCC 編譯器系列中。

這些慣用法用於讓目標的 GCC C 編譯器確定結構元素的偏移量,並將它們作為內聯彙編發出。然後使用內聯彙編生成彙編標頭檔案。

之所以這樣做是因為主機編譯器無法正確計算偏移量 - 例如,在 Linux 主機(小端,長對齊)上為 m68k(小端,短對齊)編譯。在 AROS 的歷史上,是否有任何理由不使用 #pragma pack(n) 預處理器指令?我認為,pragma pack() 可以得到跨編譯器生成結構偏移量的近似值,但 asm.c 方法可以精確地得到偏移量。對於大多數情況,pragma pack() 可能可以得到您想要的結果(特別是對於 PPC 與 m68k,它們具有相似的打包規則和相同的位元組序),但對於在 x86 上為 m68k 跨編譯來說,可能並不總是得到正確的結果。這應該保證相同的結構對齊方式和偏移量,與主機架構和正在使用的編譯器無關。OS4 和 MorphOS 使用它,vbcc 也支援它。我認為 OS4 僅將其用於已在 OS3.x 中定義的結構。新的結構不使用這種打包。在 64 位系統上,情況不會這樣,因為指標(以及替換 ULONG 的 IPTR)將佔用雙倍空間。PPC 和 m68k 的打包規則類似,x86 可能非常奇怪。我們決定使用 CPU 的本機打包,以獲得最大的速度。

不幸的是,VBCC 的內聯彙編方法不允許在彙編中進行替換操作(它會被原封不動地塞入輸出檔案),因此 asm.c 方法無法使用。這樣的功能不容易新增。即使它存在,它也無法幫助您使用 vbcc/vasm。我瀏覽了一下 asm.c,它看起來會將 #define 指令插入到彙編原始碼中。這無法與 vasm 一起使用,因為 vasm 不會在其輸入原始碼上執行 C 預處理器(最終它是一個彙編器,對 C 一無所知)。對於 AROS/VBCC 工具鏈,我僅使用 vbcc。cpp、as、ld 等來自 GCC/binutils。我不想重寫我所有的彙編器,而且我對 GNU 工具鏈的複雜性非常瞭解。但您知道 vasm 為編譯器執行所有窺孔最佳化工作嗎?如果沒有最佳化彙編器,程式碼將明顯變慢且更大。簡單。我使用 '-gas' 選項為 vbccm68k,它發出 AT&T 語法。

對於 VBCC(或 SASC,或任何其他“Amiga 風格”的編譯器),asm.c 技術不可用。之前已經討論過這個問題。有些人建議嘗試透過一些技巧從目標 .o 檔案中提取所需的資訊。另一種可能性是為每個 CPU 編寫一個 cpu.i 檔案,並讓它不要透過程式碼生成。如果讓我要求一個 *vbcc* 更改,那將是支援這種慣用法

char array[];
int func(void) = "movl #%d,d0\nret\nmova %s,a0\nmove a0@(d0),d0",1234,"array";

基本上,能夠像對待 sprintf() 字串一樣對待內聯彙編。如果我們有這個,我可以讓 asm.c 在 vbcc 下工作。您可以向函式傳遞一個引數,然後您將編寫

int func(__reg("a0") char *array) = "...";

或者您將使用一個全域性變數

int func(void) = "lea _array,a0 ...";

但您可能需要類似的東西

int func(void) = "movl #%d,d0\nrts",offsetof(struct Task, tc_State);

看起來我們被困在 GCC(可能還有 LLVM)中,適用於所有架構。是的,不幸的是,不僅用於編譯 AROS 系統,也用於編譯一般的 AROS 程式。我多年前就放棄了嘗試使用 vbcc 支援 AROS,因為 SDK 似乎是專門為 gcc 設計的,而且我不希望在每次新版本釋出時都對其進行修補。:(

我有一些補丁來支援

  • 將 -include、-iquote 和 -isystem 傳遞給 cpp
  • 支援 __section( ".with" "_string" "_concatenation")
  • Void * 算術(是的,我知道,非 C99,但 AROS 中到處都是)

哦,還有一件事。這是我的 vc.config 檔案,供您參考。

-pp=m68k-elf-cpp -P -undef -isystem /opt/vbcc/include
-I/home/jmcmullan/private/AROS.vbcc/bin/amiga-m68k/AROS/Development/include
-D__ELF__ -U__GNUC__ -D__VBCC__ -D__mc68000__ -D__mc68000 %s %s %s
-ppv=m68k-elf-cpp -P -undef -isystem /opt/vbcc/include
-I/home/jmcmullan/private/AROS.vbcc/bin/amiga-m68k/AROS/Development/include
-D__ELF__ -U__GNUC__ -D__VBCC__ -D__mc68000__ -D__mc68000 %s %s %s
-cc=vbccm68k -quiet -c99 -gas -elf %s -o= %s %s -O=%ld
-ccv=vbccm68k -c99 -gas -elf %s -o= %s %s -O=%ld
-as=m68k-elf-as %s -o %s
-asv=m68k-elf-as %s -o %s
-ld=m68k-elf-ld %s %s -o %s
-l2=m68k-elf-ld %s %s -o %s
-ldv=m68k-elf-ld %s %s -o %s
-l2v=m68k-elf-ld %s %s -o %s
-ldnodb=-s
-ul=-l%s
-cf=-F%s
-ml=500



體系結構

[編輯 | 編輯原始碼]

arch/m68k-all: 充實 m68k 通用核心例程。所有埠都需要通用的例程。特別值得關注的是 arch/m68k-all/include/gencall.c 幫助程式,它生成 GCC 粘合宏,這些宏(希望)將使我們獲得一個工作本機庫 API,而不需要太多的 GCC 補丁。

arch/m68k-all/exec/cachecleare.c 
arch/m68k-all/exec/cacheclearu.c 
arch/m68k-all/exec/cachecontrol.c 
arch/m68k-all/exec/cachepostdma.c 
arch/m68k-all/exec/cachepredma.c 
arch/m68k-all/exec/getcc.c 
arch/m68k-all/exec/mmakefile.src 
arch/m68k-all/exec/newstackswap.c 
arch/m68k-all/exec/offsets.c 
arch/m68k-all/exec/stackswap.S 
arch/m68k-all/include/aros/m68k/atomic.h 
arch/m68k-all/include/aros/m68k/cpu.h 
arch/m68k-all/include/aros/m68k/fenv.h 
arch/m68k-all/include/gencall.c 
arch/m68k-all/include/jmpdefs.h 
arch/m68k-all/include/mmakefile.src 
arch/m68k-all/mlib/fenv.c 
arch/m68k-all/mlib/mmakefile.src 
compiler/arossupport/include/atomic.h 
compiler/mlib/mmakefile.src


arch/m68k-amiga: 本機 Amiga 支援。提供對基於堆疊和 bincompat amiga-m68k 構建的支援。基於暫存器的 amiga-m68k 確實存在一些函式的編譯器問題(例如 Exec/Forbid())。

arch/m68k-amiga/boot/linkerscript 
arch/m68k-amiga/boot/m68k-gdbstub.c 
arch/m68k-amiga/boot/mmakefile.src 
arch/m68k-amiga/boot/rom_entry.S 
arch/m68k-amiga/boot/rom_init.S 
arch/m68k-amiga/boot/romcheck.c 
arch/m68k-amiga/boot/start.c 
arch/m68k-amiga/exec/coldreboot.c 
arch/m68k-amiga/exec/exec_init.c 
arch/m68k-amiga/exec/mmakefile.src 
arch/m68k-amiga/exec/preparecontext.c 
arch/m68k-amiga/exec/stackswap.s 
arch/m68k-amiga/include/mmakefile.src 
arch/m68k-amiga/include/sigcore.h 
arch/m68k-amiga/kernel/cli.c 
arch/m68k-amiga/kernel/issuper.c 
arch/m68k-amiga/kernel/kernel.conf	
arch/m68k-amiga/kernel/kernel_debug.c 
arch/m68k-amiga/kernel/kernel_init.c 
arch/m68k-amiga/kernel/maygetchar.c 
arch/m68k-amiga/kernel/mmakefile.src 
arch/m68k-amiga/kernel/sti.c 
arch/m68k-amiga/mmakefile.src 
configure.in 
rom/exec/mmakefile.src

使用通用的 exec/preparecontext.c?因為在所有系統上使其可用花費了很多時間... 必須避免使用 sigcore.h,而是使用 arch/m68k-amiga/kernel_cpu.h 並定義必要的宏。

計劃按 CPU 系列統一 CPU 上下文結構,並將其公開。或者發明一些 API 來操作上下文。因此,私有上下文是臨時性的。

尚不清楚我們是否可以在 gallium 中安全地使用 Disable()/Enable()。最好為 m68k 實現原子操作。通用原子操作可以被視為臨時技巧。不幸的是,m68k CAS 和 TAS 指令在 ChipRAM 上是非法的(參見 Amiga HRM)。我們必須在 m68k-amiga 上使用 Enable()/Disable() 進行讀-修改-寫操作。


m68k AROS_LIBFUNC_INIT 在哪裡定義?在 compiler/arossupport/include/libcall.h 中。

這可能有助於除錯 libcall 的進入和退出。

#undef AROS_LIBFUNC_INIT
#define AROS_LIBFUNC_INIT if (SysBase->DebugAROSBase) bug("+%s\n", __func__); {
#undef AROS_LIBFUNC_EXIT
#define AROS_LIBFUNC_EXIT } if (SysBase->DebugAROSBase) bug("-%s\n", __func__); }
#endif
  • 建立一個 ROM,它載入到 0xF00000 而不是 0xF80000(“卡帶”空間)
  • 位於 0xF80000 的 Amiga Kickstart 將看到 AROS ROM,並跳到它,而不是跳到它自己的 Exec(在 KS 1.3 或更高版本中會自動發生)。
  • AROS Exec 將掃描其 ROM 空間 *和* KickStart ROM 空間,並使用 KS ROM 庫來“填補”硬體驅動程式的空白。

這將使我們獲得一個“Frankenrom”,它將使更多開發人員能夠獲得一個能夠載入 AROS m68k ELF 程式並在驗證和 KS 庫替換方面進行工作的啟動 AROS。我將使用 Amiga Kickstart 3.1 的圖形、dos、滑鼠、鍵盤和 trackdisk 驅動程式來對其進行 FrankenROMing,以確保我可以進入 AROS 桌面。在那之後(這將驗證 exec.library 和 kernel.resource),我將繼續新增 AROS 庫(並刪除 KS 3.1 庫),直到全部都是 AROS。

一種更容易且更相容的方法

將 AROS ROM 留在 0xf80000 中,但將 0xE00000-0xE7FFFF 新增到 exec 的常駐結構掃描列表中。使用 romsplit 和 remus 實用程式將所需的原始 KS 模組放到 0xE00000“擴充套件 ROM”區域。

Romsplit 提取 KS rom 模組並重新建立重定位資料。Remus 可用於構建自定義 rom,將其重新定位到您想要的任何地址。

這完全相容 UAE(無需 0xf00000 技巧/UAE 啟動 rom 修改),只需配置擴充套件 rom 映像,它也更真實地相容 Amiga,1M EPROM 替換原始 ROM 會自動對映 0xE0 和 0xF8 區域。(除了那些因某種原因丟失了 1M ROM 功能的 Fat Gary 基於的 Amiga,它在 A500/A600 和 A1200 上執行良好)。真正的 CD32 也使用這種方式。CDTV 是唯一一個使用 0xF0 空間的“奇怪”的 Amiga。(0xF0 也被 Blizzard 060 卡使用)。請注意,0xE0 通常反映 0xF8(如果使用正常的 512K rom),不要意外地載入兩次模組:),還要確保安裝了 0xE0 ROM 頭,因為如果安裝了,PC 在復位時會從 0xE0 ROM 載入。


在哪裡掃描 UAE ROM 擴充套件(UAE HDF、UAE SCSI 等)?

該 ROM 通常位於 0xf00000,但也包含偽造的自動配置板,它會自動掛載。(至少在 WinUAE 中它是相對於 PC 的,可以移動到其他位置,其他 UAE 版本不確定)。

  • 記憶體對映轉儲中的“檔案系統自動配置區域”。
  • “UAE 啟動 ROM”包含程式碼。

(同樣,不確定這是否在其他 UAE 版本中報告)。

您能否在 WinUAE 中新增基於 TCP 埠的序列模擬?這將使您端的除錯工作變得更加輕鬆。我已經在我的 e-uae 中打上了補丁來實現這一功能。或者,如果您真的喜歡挑戰,您可以在 WinUAE 上實現一個 GDB 樁 TCP 埠...... 我在除錯時通常會使用單獨的 WinUAE 除錯日誌視窗,序列到 write_log() 的轉換通常已經足夠了。

在 WinUAE 中,這種工作方式需要您的 Amiga 程式呼叫一個函式。因為 uae.resource 可能會位於不同的地址,在更新的 WinUAE 中,一些額外的程式碼需要讀取向量來啟動它。

向量 20 執行強制器和序列到 WinUAE 控制檯輸出啟用。當 d1 & 1 !=0 時,強制器被啟用。當 d1 & 2 !=0 時,9600 波特率的序列資料將被髮送到 WinUAE 日誌檔案或控制檯。但在某些情況下,您可能希望更快地進行序列輸出,Toni 可能會修改程式碼,使例如 600000 波特率也能寫入控制檯,並且無需切換。

d1 & 4 != 0 是非法地址停止程式模式。這類似於死神,但在 WinUAE 中,您可以跳過對所有 AOS 圖形偵錯程式可訪問的非法地址的訪問。

所有模式都可以在執行時切換。序列模式是粘性的,因此一旦設定,在重啟後,序列資料將寫入 WinUAE 日誌控制檯或 Windows。



風格

[edit | edit source]
amiga-m68k-eabi (ELF stack based ABI) - STANDALONE (obsolete) 
amiga-m68k-aros (AROS register ABI for m68k) STANDALONE | NATIVE | BINCOMPAT

完全刪除 NATIVE。此標誌在程式碼中啟用了某些 Amiga 特定的怪癖(使用 grep 搜尋它,您會看到)。這可以透過核心中的架構特定程式碼和 CPU 特定程式碼來處理。在一些真正需要 #ifdef 的罕見情況下(比如在 a3 暫存器中返回某些內容),您可以更好地依賴 BINCOMPAT,我認為它在這裡更適合。

BINCOMPAT 風格的目標之一是消除 ROM 對於 BSS 部分的需求。此補丁刪除了 BINCOMPAT 風格的 rom/kernel 的 BSS 資料,並將 KernelBase 設定為 M68K 向量 0(位於 SysBase 正下方)。最近還有更多 BINCOMPAT 更改。請注意,目前還有其他埠是 BINCOMPAT 的,儘管它們並不真正相容,因為它們缺乏相容的結構填充。但它們將來可以真正實現二進位制相容,在支援大端 CPU 的每個埠都可以。您的埠是否在某些地方使用了 pragma pack(2)?我想我們現在應該為 BINCOMPAT 埠新增這個功能。

但即使這樣,與上述類似的更改也會破壞其他埠,因為它們可能需要這些全域性變數。在這裡我們需要另一種解決方案。我之所以會遇到所有這些問題,是因為 sam 埠不再啟動。目前,我已經將它從 ppcnative 切換到獨立模式,並且它可以正常工作了。

gcc-m68k 的所有結構都隱式地使用 pack(2)。

我不會引入太多 AROS_FLAVOUR 定義,因為目標是在 ABI V1 之後和 SDK V1 中擺脫它們。我希望使帶有全域性變數的模組可以 ROM 化。我將透過將這些全域性變數連結到一個已知位於 RAM 中的絕對地址來做到這一點。然後,第一個 ROM 初始化程式碼將保留全域性變數連結位置的適當數量,並進行初始化。

AROS_FLAVOUR_NATIVE

使用本地作業系統的系統呼叫而不是核心

AROS_FLAVOUR_STANDALONE

使用核心直接控制排程

AROS_FLAVOUR_EMULATION

???

AROS_FLAVOUR_LINKLIB

???

AROS_FLAVOUR_BINCOMPAT

與 AmigaOS 3.x API 二進位制相容(PPC 和 M68K)

我想新增一些類似於以下內容的內容

AROS_FLAVOUR_ROM

rom/* 庫中不允許使用 .bss 或 .data 段

如果我們在 ABI V1 切換之前保留當前標誌,則不應該有任何問題。對於 sam 和 efika 埠以及以下程式碼行

  1. if (AROS_FLAVOUR & AROS_FLAVOUR_BINCOMPAT)

我需要更多資訊,以確定這是用於 Amiga 硬體還是僅用於二進位制相容。目前,16 位元組堆疊對齊不起作用,或者存在一些直接硬體訪問操作。這可以透過使用更多預處理器符號(哪些符號?)重寫,這些符號被分離到架構相關的宏或行內函數中,或者被 build_arch_specific 覆蓋。

我不知道 ABI V1 將如何更改風格相關的設定,但我假設需要有關 AROS_TARGET_ARCH 和 AROS_TARGET_CPU 的資訊,那麼現在將這些資訊放在我們生成的 config.h 中如何?然後,這些資訊可以幫助解決上述問題。


好的,我想要 config.h 包含類似以下內容的東西

  1. define AROS_TARGET_ARCH_AMIGA
  2. define AROS_TARGET_CPU_M68K

  1. define AROS_TARGET_ARCH_SAM440
  2. define AROS_TARGET_CPU_PPC

<其他內容>

具體取決於 configure 的呼叫方式。

一些託管模組中使用的預處理器符號,例如 HOST_OS_linux、HOST_OS_darwin 或 AROS_ARCHITECTURE,可以以相同的方式生成並放置在 config.h 中。您能否進行 configure.in 的更改,然後我會“趕上”並修復程式碼,在需要的地方使用這些符號來代替 BINCOMPAT。


或者,它應該是一個單獨的“CONFIG_ROMMABLE”之類的符號嗎?

AmigaOS Exec 的一個基本優點是,(透過新增一些硬體互斥體)帶有 MMU 的 SMP 支援非常簡單。每個 CPU 都有自己的記憶體空間,以及自己的 SysBase,您可以建立一個特殊的 CPU 間訊息管道來向其他 CPU 傳送訊息。

一種方法是讓(例如)CPU0 控制所有硬體,所有其他 CPU 都有代理庫,這些庫使用 GetMsg() 來“向上呼叫”CPU0 以進行硬體訪問。

當然,您也可以將硬體訪問分配給不同的 CPU,或者其他任何可能性。所有 CPU 都使用相同的只讀記憶體來儲存 Exec/Intuitiuon/etc 庫,但每個庫的 LibBase 對每個 CPU 都是私有的。

我不明白這兩者之間如何發生衝突。可能 SMP 感知驅動程式不會為了效率而使用全域性變數,但這並不意味著應該禁止所有驅動程式使用全域性變數。我希望能夠將任何驅動程式或庫放到 ROM 中。例如,對於具有數 MB 非易失性記憶體的移動裝置。為每個 CPU/核心提供自己的記憶體空間,當您想在 CPU/核心之間移動程序時會產生問題。我會為每個 CPU 提供一個 SysBase 的副本,但我將使用 MMU 將其定位在相同的虛擬地址空間。這樣就可以在 CPU/核心之間移動程序。

舊式 Amiga 中斷處理程式的條件程式碼標誌 Z 位於 %sr 中,用於確定處理程式是否處理了 IRQ。不幸的是,真的沒有乾淨的方法來同時支援舊式和新式中斷處理程式,因此對於 BINCOMPAT,我們將忽略返回值,並處理所有處理程式。



標誌和呼叫

[edit | edit source]

為什麼在配置 AROS 時不將 TARGET_CC & TARGET_CFLAGS 和 HOST_CC & HOST_CFLAGS 作為可選變數呢?只需使用眾所周知的預設值來處理常見情況。如果我們想使用其他編譯器,這將更加靈活。

AROS_LC(庫呼叫)宏應該使用 AROS_LD(庫宣告)系列進行型別轉換 - AROS_LP(庫原型)用於 C 樁和原型,而不是用於庫 ABI。

In the __AROS_LP_BASE(basetype,basename) macro, it is unsafe to ever use or return the 'basetype' element, since it is frequently corrupted by #defines, for example:

struct foo_data {
   struct GfxBase *GfxBase;
   ...;
}

#define GfxBase data->GfxBase

...

int blah_blah(struct foo_data *data, ...)
{
    AddDisplayDriverA(gfxhidd, &tags);
    ...
}

In the above example, AddDisplayDriverA is defined as a call to __AddDisplayDriverA_WB(GfxBase, (arg1), (arg2)), which uses the AROS_LC2() macro, which uses the __AROS_LP_BASE() macro to cast the type. If __AROS_LP_BASE() returns the basetype, the macro expands to the following for the cast of the function pointer: 

(LONG (*)(APTR, struct TagItem *,struct GfxBase *))

Which is all fine, until GfxBase gets expanded:

(LONG (*)(APTR, struct TagItem *,struct data->GfxBase *))

So, if '#defineing' lib bases is an allowed idiom, then
__AROS_LP_BASE() must never return basetype, correct?
When I compiled some AROS libs (like diskfont.library) under AOS/68k I used:

/* What to do with the library base in header, prototype and call */
#define __AROS_LH_BASE(basetype,basename)   register basetype basename __asm("a6")
#define __AROS_LP_BASE(basetype,basename)   register void * __asm("a6")
#define __AROS_LC_BASE(basetype,basename)   basename
#define __AROS_LD_BASE(basetype,basename)   register basetype __asm("a6")

/* How to transform an argument in header, prototype and call */
#define __AROS_LHA(type,name,reg)     register type name __asm(reg)
#define __AROS_LPA(type,name,reg)     register type __asm(reg)
#define __AROS_LCA(type,name,reg)     name
#define __AROS_LDA(type,name,reg)     register type __asm(reg)
#define __AROS_UFHA(type,name,reg)    register type name __asm(reg)
#define __AROS_UFPA(type,name,reg)    register type __asm(reg)
#define __AROS_UFCA(type,name,reg)    name
#define __AROS_UFDA(type,name,reg)    register type __asm(reg)

 #define __AROS_LP_BASE(basetype,basename)   register void * __asm("a6")
 #define __AROS_LPA(type,name,reg)     register type __asm(reg)

您是否意識到,這使得您所有的 C 樁都變成了 regcall 而不是 stack call?我不知道這些 C 樁是否真的被使用了。它們在幾年前根本不存在。我認為 AROS_LP 宏不是/不打算用於 C 樁的原型。它們旨在用於真實 libcall 的原型(即使由於 libcall 的實現方式而很少使用)。C 樁的原型使用 AROS_LP 宏也是不合理的,而在實際實現(生成的 #?_stubs.c 檔案)中根本沒有使用任何宏。因為這意味著 AROS_LP 宏將始終需要“擴充套件”到正常的 C 呼叫約定 -> 為什麼一開始要使用 AROS_LP 宏呢?

正確的行為是將它們用於真實庫呼叫的原型,而不是用於樁。在過去,可能有一些奇怪的編譯器需要單獨的原型和定義,或者它只是額外的相容性。它們可能從 rev 1 或更早的版本開始就存在了。因此,我個人更願意保留它們並修復樁。

  1. define 被認為是一種技巧,應該避免使用。當使用它們時,人們應該注意不要引起問題。這並不是 AROS_LP 宏的責任來修復它。在 ABI V1 分支中,有一種機制可以幫助您擺脫所有這些 #define 語句。

AROS_UFCx() 應該*只*用於 regcall 例程。如果 VNewRawDoFmt() 需要一個 stackcall 例程,請勿使用 AROS_UFCx()。只需宣告一個普通的 C 例程即可。是的,MorphOS 就是這樣做的。對於這種破壞性更改,我感到很抱歉。我在完成文件之前就實現了 VNewRawDoFmt()。我非常確定沒有人使用過它來執行自定義回撥例程。事實上,在 exec/rawfmt.h 中宣告的魔術常量涵蓋了函式使用量的 99%。

我注意到 AROS 程式載入速度比 AOS 上慢很多。我查看了 AROS 原始碼,看起來檔案操作到 load_block 會經過多個角落,並且在使用 fgetc 時看起來很慢。為什麼 load_block 函式不能直接執行 AOS 讀取?ELF 檔案的位元組序是否與 68k 平臺的位元組序不同?一個塊的大小是否不超過 4 KB?如果是,使用直接讀取總是比使用 fgetc(從 ELF 載入程式呼叫)快很多。

static void * load_block
(
    BPTR               file,
    ULONG              offset,
    ULONG              size,
    LONG              *funcarray,
    struct DosLibrary *DOSBase
)
{
    void *block = MyAlloc(size, MEMF_ANY);
    if (block)
    {
        if (read_block(file, offset, block, size, funcarray, DOSBase))
            return block;

        MyFree(block, size);
    }
    else
        SetIoErr(ERROR_NO_FREE_STORE);

    return NULL;
}

here are the lots of corner snippets that do at end only load some bytes in.

.........................

static int read_block
(
    BPTR               file,
    ULONG              offset,
    APTR               buffer,
    ULONG              size,
    LONG              *funcarray,
    struct DosLibrary *DOSBase
)
{
    UBYTE *buf = (UBYTE *)buffer;
    LONG   subsize;

    if (Seek(file, offset, OFFSET_BEGINNING) < 0)
        return 0;

    while (size)
    {
        subsize = MyRead(file, buf, size);

        if (subsize <= 0)
        {
            if (subsize == 0)
                SetIoErr(ERROR_BAD_HUNK);

            return 0;
        }

        buf  += subsize;
        size -= subsize;
    }

    return 1;
}

#define MyRead(file, buf, size)      \
    AROS_CALL3                       \
    (                                \
        LONG, funcarray[0],          \
        AROS_LCA(BPTR,   file, D1),  \
        AROS_LCA(void *, buf,  D2),  \
        AROS_LCA(LONG,   size, D3),  \
        struct DosLibrary *, DOSBase \
    )


static AROS_UFH4(LONG, ReadFunc,
    AROS_UFHA(BPTR, file,   D1),
    AROS_UFHA(APTR, buffer, D2),
    AROS_UFHA(LONG, length, D3),
        AROS_UFHA(struct DosLibrary *, DOSBase, A6)
)
{
    AROS_USERFUNC_INIT

    return FRead(file, buffer, 1, length);

    AROS_USERFUNC_EXIT
}



最佳化

[edit | edit source]

最佳化就像修復 bug 一樣,雖然您希望建立完美的產品,但現實情況是您的生命週期有限,並且您首先要解決最大的問題。如果程式非關鍵部分中的小錯誤沒有導致產品無法使用,那麼即使它們沒有被修復也沒關係。同樣,如果很少使用的慢速例程永遠不會被替換,因為總體速度提升可能是微不足道的。

兩者之間的區別在於,bug 是絕對的:某件事要麼在所有情況下都按照預期和允許的方式執行,要麼不執行。如果不執行,那麼導致這種情況的原因被稱為 bug。另一方面,最佳化是相對的。對於速度最佳化,存在權衡。您始終可以獲得比當前解決方案更快的速度,但代價是犧牲一個或多個其他因素,例如記憶體使用量、磁碟空間或可維護性。

在開發中,尤其是可維護性成本是一個問題:如果您仍在開發,但為了速度而使程式碼變得難以理解,那麼就無法找到剩餘的 bug。通常,這被稱為“最佳化一個工作程式比讓一個最佳化的程式工作更容易”。因此,在開發中,對於相同的程式碼段,修復 bug 的優先順序高於速度最佳化。

這將是一個非常奇怪的現象。速度和清晰度通常是相互權衡的。是什麼其他因素被優化了,導致這兩者都受到了影響?

不,一個好的編譯器可以為大多數抽象型別建立相當好的程式碼,包括面向物件程式設計。可能確實會有一些速度損失,因為這是為了獲得更清晰的原始碼而付出的代價。當然,更清晰的原始碼使除錯更容易,而不是更難。

Knud 提到一些程式設計師試圖編寫高度最佳化的程式碼,這會導致除錯和維護方面出現重大問題。他認為,在 97% 的情況下,最佳化都是浪費。然後他說,過早最佳化是不好的,但我們應該最佳化那 3% 的程式碼。(言外之意是,在確定程式碼屬於那 3% 之前,不應該進行最佳化。) 在 AROS 中,只有少數效能瓶頸,例如 exe 載入、圖示庫和 OO。當修復這些問題並且不最佳化其他程式碼時,AROS 對使用者的響應速度會大幅提升。這確實與 Knud 的觀點一致:如果我們知道 exe 載入、圖示庫或 OO 屬於那 3%,無論它們是什麼,都應該針對速度進行最佳化。


發現傳遞給 DoSuperNew() 的屬性列表在到達超類的 OM_NEW 方法時已失效(例如,只有第一個 ti_Tag 值大於 0x80000000)。可以透過將 NList_mcc.c 和 NListview.c 的編譯選項設定為 -O0 來解決此問題。

我懷疑 GCC 在啟用最佳化時會將 DoSuperNew() 方法內聯到這些檔案中,因此不會將變長引數放在堆疊上,結果會導致傳遞給 DoSuperMethod() 的 &tag1(AROS_SLOWSTACKTAGS_ARG(tag1)) 作為屬性列表,其後不一定跟著剩餘的標籤。這可能意味著我們不能再在 i386 上不用 AROS_SLOWSTACKTAGS 了,因為我們不應該假設變長引數位於堆疊上(而應該使用 va_list 等)。引入 ABIv0 的 SLOWSTACKTAGS 會破壞二進位制相容性嗎?



GCC 補丁

[編輯 | 編輯原始碼]

我的 GCC 4.5.1 補丁還沒有準備好供大眾使用。我仍然在任務就緒和等待列表中遇到列表損壞問題,我開始擔心隱藏著 GCC 的錯誤。

From f68b80717efec2ccf4c181c9a3fc4184fde27be1 Mon Sep 17 00:00:00 2001
From: Jason S. McMullan <jason.mcmullan AT netronome.com>
Date: Sun, 10 Oct 2010 00:38:26 -0400
Subject: [PATCH] [m68k-amiga] Amiga ABI support

Moves the FP to A5, doubling up with the PIC
Breaks all -fpic modes.

NOT FOR UPSTREAM: This breaks *all* other m68k APIs!!!

Signed-off-by: Jason S. McMullan <jason.mcmullan AT netronome.com>
---
 gcc/config/m68k/m68k.c  |    8 ++++----
 gcc/config/m68k/m68k.h  |    6 +++---
 gcc/config/m68k/m68k.md |    4 ++--
 3 files changed, 9 insertions(+), 9 deletions(-)

diff --git a/gcc/config/m68k/m68k.c b/gcc/config/m68k/m68k.c
index c22f3b8..9718ccb 100644
--- a/gcc/config/m68k/m68k.c
+++ b/gcc/config/m68k/m68k.c
@@ -920,7 +920,7 @@ m68k_initial_elimination_offset (int from, int to)
 static bool
 m68k_save_reg (unsigned int regno, bool interrupt_handler)
 {
-  if (flag_pic && regno == PIC_REG)
+  if (flag_pic && regno == A5_REG)
     {
       if (crtl->saves_all_registers)
 	return true;
@@ -2186,7 +2186,7 @@ static rtx
 m68k_get_gp (void)
 {
   if (pic_offset_table_rtx == NULL_RTX)
-    pic_offset_table_rtx = gen_rtx_REG (Pmode, PIC_REG);
+    pic_offset_table_rtx = gen_rtx_REG (Pmode, A5_REG);
 
   crtl->uses_pic_offset_table = 1;
 
@@ -4640,7 +4640,7 @@ m68k_delegitimize_address (rtx orig_x)
   if (GET_CODE (x) == PLUS
       && GET_CODE (XEXP (x, 1)) == CONST
       && REG_P (XEXP (x, 0))
-      && REGNO (XEXP (x, 0)) == PIC_REG)
+      && REGNO (XEXP (x, 0)) == A5_REG)
     {
       y = x = XEXP (XEXP (x, 1), 0);
 
@@ -5145,7 +5145,7 @@ m68k_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED,
 
   /* Restore the original PIC register.  */
   if (flag_pic)
-    SET_REGNO (pic_offset_table_rtx, PIC_REG);
+    SET_REGNO (pic_offset_table_rtx, A5_REG);
 }
 
 /* Worker function for TARGET_STRUCT_VALUE_RTX.  */
diff --git a/gcc/config/m68k/m68k.h b/gcc/config/m68k/m68k.h
index 5787e8a..1d36a63 100644
--- a/gcc/config/m68k/m68k.h
+++ b/gcc/config/m68k/m68k.h
@@ -348,7 +348,7 @@ along with GCC; see the file COPYING3.  If not see
 #define PIC_OFFSET_TABLE_REGNUM				\
   (!flag_pic ? INVALID_REGNUM				\
    : reload_completed ? REGNO (pic_offset_table_rtx)	\
-   : PIC_REG)
+   : A5_REG)
 
 /* 1 for registers that have pervasive standard uses
    and are not available for the register allocator.
@@ -416,7 +416,7 @@ along with GCC; see the file COPYING3.  If not see
 	  fixed_regs[i] = call_used_regs[i] = 1;		\
     }								\
   if (flag_pic)							\
-    fixed_regs[PIC_REG] = call_used_regs[PIC_REG] = 1;		\
+    fixed_regs[A5_REG] = call_used_regs[A5_REG] = 1;		\
 }
 
 /* On the m68k, ordinary registers hold 32 bits worth;
@@ -453,7 +453,7 @@ along with GCC; see the file COPYING3.  If not see
 /* Most m68k targets use %a6 as a frame pointer.  The AmigaOS
    ABI uses %a6 for shared library calls, therefore the frame
    pointer is shifted to %a5 on this target.  */
-#define FRAME_POINTER_REGNUM A6_REG
+#define FRAME_POINTER_REGNUM A5_REG
 
 /* Base register for access to arguments of the function.
  * This isn't a hardware register. It will be eliminated to the
diff --git a/gcc/config/m68k/m68k.md b/gcc/config/m68k/m68k.md
index f89037f..9f3da5a 100644
--- a/gcc/config/m68k/m68k.md
+++ b/gcc/config/m68k/m68k.md
@@ -131,7 +131,7 @@
   [(D0_REG		0)
    (A0_REG		8)
    (A1_REG		9)
-   (PIC_REG		13)
+   (A5_REG		13)
    (A6_REG		14)
    (SP_REG		15)
    (FP0_REG		16)
@@ -7295,7 +7295,7 @@
 {
   if (TARGET_ID_SHARED_LIBRARY)
     {
-      operands[1] = gen_rtx_REG (Pmode, PIC_REG);
+      operands[1] = gen_rtx_REG (Pmode, A5_REG);
       return MOTOROLA ? "move.l %?(%1),%0" : "movel %1@(%?), %0";
     }
   else if (MOTOROLA)
-- 
1.7.1




函式地址透過在庫的 .conf 檔案中列出它們來放置在庫的 LVO 表中。在庫中的任何位置,無論呼叫鏈有多深,都可以使用 AROS_GET_LIBBASE 宏訪問庫基址(實際上只是檢索 %ebx 指向地址的值)(x86 程式碼)。那麼,除了浪費 %bx 暫存器之外,這對於現有程式碼(已經將庫基址傳遞給需要它的子函式)有什麼優勢呢?

在這種情況下,沒有真正的優勢,因為該程式碼已經繞過了當前 Amiga 共享庫實現的缺陷。對於新的程式碼,可以節省每次函式呼叫時壓入堆疊的所有 libbases 所佔用的堆疊空間。

我個人沒有看到在 i386 上實現它的方法,除非為它保留 %ebx。我選擇 %ebx,因為它在 SYSV 中被記錄為位置無關程式碼的全域性偏移表基址暫存器;我發現它有點相關。

如果您打算使用 %bx 暫存器,也許使用 -fPIC 編譯的程式碼會更好,並使用 %bx 指向該 OpenLibrary() 例項的 ELF GOT 表。這將使所有埠更容易,因為 -fPIC 對於 ARM、x86、x86_64、m68k 和 PPC 都有明確定義。

我快速瀏覽了一下,但似乎在 i386 上,生成的 __GLOBAL_OFFSET_TABLE__ 是一個地址,所以訪問是透過地址而不是透過暫存器完成的。這在 AROS 上會帶來問題,因為 AROS 只有一個地址空間,共享庫只加載到記憶體中一次。

我對 -fPIC 的第二個問題是它是一種非此即彼的方法:當您指定它時,所有對全域性變數的訪問都透過 __GLOBAL_OFFSET_TABLE__ 完成。我想要繼續支援當前情況,其中只有顯式放在庫基址中的欄位是每個開啟器(每個任務)的,而其餘的全域性符號是共享的。

總的來說,我發現 -fPIC 太過面向 UNIX 系統,UNIX 系統有虛擬記憶體和每個程序都有獨立的地址空間。我不是這方面的專家,所以對於我可能做出的任何錯誤結論,我持開放態度。

但我確實需要類似於 -fPIC 但適應 AROS 架構的東西:- 在所有 CPU 上透過暫存器呼叫完成 - 能夠在存根程式碼中設定暫存器 - 能夠記住暫存器的先前值並在函式呼叫後恢復它。我認為如果使用 -fPIC,這還沒有解決,因為我認為它是在連結時遇到 .so 時解決的。

我當然不想將 .so 共享物件概念複製到 AROS(就像 AOS4 所做的那樣)。- 只有為 libbase 保留暫存器,預設情況下不要透過 GOT 對所有全域性變數進行定址。

對於 m68k,我認為我們想要的 -fPIC 編譯選項是

-fPIC -msep-data

如果指定此選項,對 m68k 的影響是什麼?我該如何透過這種機制傳遞 libbase?

我還忘了說,我打算在 %ebx 中使用 libbase,以便能夠在不需要這些醜陋的 #define xxxBase 技巧的情況下擁有沒有 .bss 或 .data 部分的模組。

最終,我認為我們必須深入研究一些編譯器的內部。無論是 LLVM 還是 GCC,我認為選擇 AROS 編譯器並開始對其進行調整以滿足我們的需求的時機已經到來。

我甚至更進一步 - 正確使用可變引數列表會帶來如此大的改變嗎?AROS 看起來是一個研究型作業系統,不正確使用可變引數列表是可以在很大程度上改進的地方之一…… 可變引數列表對於 x86_64 來說尤其成問題,因為 sizeof(void*) != sizeof(int)。

儘管我很想正確使用它們,但隱式可變引數列表在幾乎所有使用 BOOPSI 的 Amiga 原始碼中都被大量使用(並被濫用)。

打破這種假設會破壞類似這樣的程式碼(根據我移植到 x86_64 的經驗,這種程式碼非常普遍)。

struct fooStruct {
     int a;
     char b;
     void *c;
};

struct booStruct {
    long qux;
    char *name;
};

#define fooID 0xf00
#define booID 0xb00

void handleMethod(ULONG methodID, ...)
{
   struct fooStruct *foo;
   struct booStruct *boo;

   switch (methodID) {
   case fooID:
       foo = (struct fooStruct *)((&methodID)+1);
       handleFoo(foo);
       break;
   case booID:
       foo = (struct booStruct *)((&methodID)+1);
       handleBoo(boo);
       break;
   }
}

...

handleMethod(fooID, 1, 'd', &somebuffer);

handleMethod(booID, 99, "Hello World");



`.data' 無法放入區域 `invalid' /home/mike/amigaos/aros-m68k-bin/lib/gcc/m68k-elf/4.5.1/../../../../m68k-elf/bin/ld: 區域 `invalid' 溢位 136 位元組

這意味著在某個地方存在一些非常量(不可 ROM 化)資料。

編輯 arch/m68k-amiga/boot/rom.ld,找到 "invalid (rwx)" 行,將 l = 0x0 替換為 l = 0x100(或其他大於 136 的值)。現在應該可以編譯了(但無法執行)。

列出不正確的資料符號

m68k-elf-nm -ln <huge rom image.elf> | grep dead

請務必撤銷對 rom.ld 的更改,如果忘記了修改並報告了將來因非法 0xdeadxxxx 地址導致的所謂的崩潰“錯誤”,我們概不負責。:)



哦,我計劃在呼叫程序的 tc_TrapCode 時,使 m68k 異常在堆疊上與 AmigaOS 完全一致,但我需要知道 AROS 核心 Sonic 正在開發的內容的期望。

透過使用 %a6 的暫存器宣告,gcc 假設所有對 %a6 的使用都是對 AROS_GET_FP 全域性變數的引用。

要獲取幀指標,您不能依賴 %fp(或 %bp,或任何類似的東西),因為如果使用 -fomit-frame-pointer,GCC 可能會覆蓋它。

__builtin_frame_address(1) 應該是這種情況下所需要的(呼叫例程的幀指標)。

無論如何,%a5 都是 AROS/m68k 下的幀指標,而不是 %a6。

我現在正在編譯和測試它,但這是根據“git bisect”得出的結論。


修復構建。exec/types.h 沒有定義 size_t,sys/types.h 定義了它。

stddef.h 更好,因為它符合 ANSI-C。sys/types.h 符合 POSIX。



我在 AROS 程式碼中搜索 text bestcmodeid,但我沒有看到 Wanderer 使用它。所以我想我的 modeid 與安裝不匹配。使用 bestcmodeidtags 是最好的,因為 P96 模式編號在所有 winuae 系統上都不同。也許 Wanderer 可以改變?

以下程式碼來自 SDL。如果這裡沒有螢幕解析度,此命令將自動提供下一個可能的 modeid。

        okid=BestCModeIDTags(CYBRBIDTG_NominalWidth,SDL_Display->Width,
                CYBRBIDTG_NominalHeight,SDL_Display->Height,
                CYBRBIDTG_Depth,bpp,
                TAG_DONE);
        }

以下是一些顯示如何使用 P96 設定特定畫素格式的原始碼。它在 68k P96 和 68k CGX 上進行了測試,並在 Amiga GFX 卡上也報告工作正常。

        if (bpp == 16)
      {
          UWORD pixfmt[] ={PIXFMT_RGB16,-1};
        unsigned long *ret;
          struct CyberModeNode * cnode;
        ret = AllocCModeListTags(CYBRMREQ_MinWidth,width,CYBRMREQ_MinHeight,height,
            CYBRMREQ_MaxWidth,width+1000,CYBRMREQ_MaxHeight,height+1000,
            CYBRMREQ_MaxDepth,bpp,CYBRMREQ_MinDepth,16,CYBRMREQ_CModelArray,&pixfmt,TAG_END);
            if (ret)
                  {cnode = *ret;
                  if (cnode)okid = cnode->DisplayID;
                  }
      if (!IsCyberModeID(okid))okid = INVALID_ID;
      kprintf(" RGB16  Mode ID %lx\n",okid);
      }

也許是我的某些 winuae 設定。是否存在已知可以正常工作的 winuae 配置檔案?


有人知道 m68k 的 ABI 參考嗎?我感興趣的是函式呼叫的引數傳遞。所有 C 語言引數都透過堆疊傳遞(對於非 LVO 呼叫)。C 函式的返回值位於 D0 中。暫存器 D0/D1 和 A0/A1 可以被被呼叫函式用作臨時暫存器,呼叫者必須預期它們會被破壞。暫存器 D2-D7 和 A2-A7 必須被被呼叫函式保留。(一些編譯器允許每個引數進行覆蓋,但它們會顯式地將暫存器對映到引數)。

更具體地說:誰在函式呼叫期間擁有 A6?呼叫者。它是否在函式呼叫中被保留?是的,如果被呼叫函式修改了它,則必須保留它。

暫存器 A6 是 LibBase,A5 是幀指標(可選),A4 是指向 .data/.bss 區域的指標(對於某些編譯器)。

A6 是該庫的 libbase,圖形庫中的大多數庫內呼叫都是 LVO(暫存器)呼叫,所以這並不奇怪。

GfxBase 是一個 LVO 呼叫。

在 AmigaOS 中,有三種或四種主要的呼叫約定,具體取決於你問誰。我寫的都是憑記憶,所以不要完全相信我說的話。

C 呼叫約定:慢如冰凍的糖蜜,將所有內容都透過堆疊傳遞。支援可變引數列表,但除此之外幾乎毫無用處,通常會最佳化為另一種呼叫約定。返回值在 D0 中。不應與共享庫一起使用,除非用於可變引數列表存根呼叫。

LVO 呼叫約定:LibCalls 始終允許將 D0/D1/A0/A1 用作臨時暫存器,並且不會被子例程保留。剩餘的暫存器必須被子例程保留。A6 暫存器始終在此呼叫約定期間儲存庫基址。可以保留 A4 中的全域性變數和區域性變數堆,除非使用大資料模型。可以使用 A5 中的可選幀指標進行除錯。

標準呼叫約定:與 LVO 呼叫約定相同,只是不需要庫基址。需要使用 C 呼叫約定編寫的存根函式來實現可變引數列表,因為它們在此處不受支援。


有任何基準測試證實這種速度緩慢嗎?如果它真的那麼慢,為什麼 C 呼叫函式會被用於非庫呼叫?當然,這種影響在沒有資料快取且只有晶片記憶體的 CPU 上最為明顯。我們應該讓 m68k AROS 編譯器對所有函式呼叫使用暫存器引數傳遞嗎?

也就是說,堆疊快取只存在於 '060 上,因此暫存器傳遞絕對是優先考慮的。C 呼叫約定之所以使用,僅僅是為了可變引數列表。沒有其他理由使用 C 呼叫約定。使用暫存器傳遞的標準呼叫約定要常見得多。

此外,關於 LLVM 的呼叫約定,該編譯器還支援另一種稱為“cold”呼叫約定的約定,用於不太常呼叫的子例程,並且在呼叫它們時,需要儘可能少地接觸暫存器。在 68k 上,這意味著只使用臨時暫存器和堆疊,而不會覆蓋任何其他暫存器。它只用於最佳化和與 LLVM 的相容性。

雖然 Aros-m68k 不需要 MMU,但 68030 和 68040 使用不同的管理指令訪問暫存器,(部分)不同的管理暫存器,以及不同的暫存器位對映和頁面描述符。68030 MMU 確實支援更多頁面大小,並且總體上更靈活。為了提高速度並降低複雜度,68040 簡化了 MMU 設計。68040 和 68060 的 MMU 幾乎相同,68060 只是在 mmu 表快取和重新命名一些快取模式方面添加了一些限制。68060 上的 MMU 異常處理也不同。



記錄一下,我寫了 Haiku 中核心 elf 載入器 的 m68k 部分:(雖然現在還沒有測試過,但核心目前無法構建)

順便說一下,我在 Ti92 時代 (1997 年) 的檔案中找到了一個用於將 HUNK 支援新增到 BFD 的舊 binutils 補丁,當然可以移植到更新的 binutils。奇怪的是,沒有人保留它。我還記得寫了一些程式碼來讀取 hunks 以轉換為 ti 格式。(第一次 Ti 68k 開發是使用 a68k 完成的,有些人使用 amiga 交叉編譯器,早於 tigcc 時代。)

華夏公益教科書