You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/static/asm.rst
+43-53Lines changed: 43 additions & 53 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,60 +1,50 @@
1
1
.. _asm:
2
2
3
-
Assembly Routines
4
-
=================
3
+
Assembly Files
4
+
==============
5
5
6
-
Assembly routines can be linked into a C/C++ program by putting them into the same **src** directory that your C/C++ sources are in, but with an **.asm** extension.
7
-
These can be placed in any subdirectory of **src** just like C/C++ sources.
6
+
Assembly files can be linked into a C/C++ program by putting them into the same **src** directory that your C/C++ sources are in.
7
+
Use a **.S** extension if you want the compiler's preprocessor to run on the file first, or use a **.s** extension if the assembly file does not need to be preprocessed.
8
8
9
-
Assembly Files
10
-
--------------
9
+
The use of inline assembly is supported, but highly discouraged as future changes to the compiler may render the inline assembly incompatible, and it reduces the readablity of the code.
10
+
11
+
Assembler
12
+
---------
11
13
12
-
.. _asm-consts:
14
+
The CE Toolchain uses the GNU Assembler (GAS) to assemble source files.
15
+
Historically the fasmg assembler was used, but is no longer supported to allow for better cross-platform support and linking performance.
13
16
14
-
Constants
15
-
^^^^^^^^^
17
+
Documentation for the GNU Assembler: https://www.sourceware.org/binutils/docs/as/index.html
16
18
17
-
The top of the file is a good place defining constants or including other files that define constants.
18
-
These will be availabe throughout the rest of the file, but not in other files.
19
-
You can define a constant by saying :code:`my_constant := 42`.
20
-
You can include common constants in multiple files by defining them in a file named, say, **file.inc** and putting :code:`include 'file.inc'` in every file that needs them.
21
-
You should not generally put any labels, code, or data here.
22
-
If you try to reference a label defined here, you will get an :code:`Error: variable term used where not expected.` linker error which means you are trying to resolve an address that doesn't belong to any section.
23
-
See :ref:`asm-section` to fix this problem.
19
+
Specific Z80/ez80 directives: https://www.sourceware.org/binutils/docs/as/Z80-Directives.html
24
20
25
21
.. _asm-assume:
26
22
27
23
Assume
28
24
^^^^^^
29
25
30
-
You should add a :code:`assume adl=1` before trying to emit any code, which ensures that you get 24-bit eZ80 instructions.
31
-
If you end an assembly file with :code:`assume adl=0` (which is the eZ80's 16-bit Z80 compatibility mode), it will propogate to another random assembly file.
32
-
All toolchain and compiler-generated sources make sure to reset the mode at the top of the file and end the file in the same mode, but if one of your sources end in Z80 mode, then any other one of your sources might begin in Z80 mode, so it is safer to put the :code:`assume` line in every file.
26
+
You should add a :code:`.assume ADL=1` before trying to emit any code, which ensures that you get 24-bit eZ80 instructions.
33
27
34
28
.. _asm-section:
35
29
36
-
Section
37
-
^^^^^^^
30
+
Sections
31
+
^^^^^^^^
38
32
39
-
Now that we are in the correct mode, we need to tell the linker where to put things.
40
-
We use :code:`section .text` for code, :code:`section .data` for variables, and :code:`section .rodata` for constant data.
41
-
Currently these are all placed in RAM, so which section you choose to switch to is much less important than how often you switch sections, even if you are switching to the same section you are already in.
42
-
This is because every time you start a new, or restart the same, section, the linker gets a new opportunity to delete a block of dead code/data.
33
+
The CE Toolchain uses :code:`.section .text` for code, :code:`.section .data` for variables, and :code:`.section .rodata` for constant data.
34
+
Every time you start a new section (such as :code:`.section .text.function`), the linker has an opportunity to delete a block of dead code/data.
43
35
Because of this, the correct time to switch sections is usually every time you start a new function or variable.
44
-
You should not let execution fall off the end of a block because you won't know if that block will be included or deleted from the output, however you can if you say :code:`require _symbol` of some public or private symbol defined in the next section to ensure that if the current block is included, then that will force the next block to also be included.
45
-
To define a symbol in a block that can be referenced from other blocks, you should do :code:`private _symbol` or :code:`public _symbol` right before its definition.
46
-
If it is private then it is only able to be referenced from the same file and no :ref:`extern <asm-extern>` should be used.
47
-
If it is public then it can be referenced within the same file without :ref:`extern <asm-extern>` just like private symbols, but public symbols can also be referenced from other files and even C/C++!
48
-
The public assembly symbol named :code:`_symbol` is accessible in C by the global name :code:`symbol`, assuming it is properly declared, with your asm symbol acting as the definition.
36
+
To define a symbol in a block that can be referenced from other blocks, you should do :code:`.local _symbol` or :code:`.global _symbol` right before its definition.
37
+
If it is local then it is only able to be referenced from the same file and no :ref:`.extern <asm-extern>` should be used.
38
+
If it is global then it can be referenced within the same file without :ref:`.extern <asm-extern>` just like local symbols, but global symbols can also be referenced from other files and even C/C++!
39
+
The gllobal assembly symbol named :code:`_symbol` is accessible in C by the global name :code:`symbol` (note the leading underscore), assuming it is properly declared, with your asm symbol acting as the definition.
49
40
50
41
.. _asm-extern:
51
42
52
43
Extern
53
44
^^^^^^
54
45
55
-
At the end of the file is a good place to list every external symbol that you might depend on like :code:`extern _symbol`.
56
-
This includes both public symbols defined in another assembly file and global symbols from C, prefixed with an underscore like usual.
57
-
Lastly, you should not let execution fall off the end of a file because the next file that gets assembled is unpredictable and you could end up anywhere!
46
+
At the end of the file is a good place to list every external symbol that you might depend on like :code:`.extern _symbol`.
47
+
This includes both global symbols defined in another assembly file and global symbols from C, prefixed with an underscore.
58
48
Block ordering can only be relied on within a single file, and only for blocks belonging to the same section.
59
49
60
50
Linking ASM routines to C/C++
@@ -69,17 +59,18 @@ Below is an example C prototype followed by the assembly implementation:
69
59
70
60
.. code-block:: c
71
61
72
-
void asm_func(int arg);
62
+
void asm_func(int argument);
73
63
74
64
:code:`asm_func.asm`
75
65
76
66
.. code-block::
77
67
78
-
assume adl=1
79
-
80
-
section .text
81
-
82
-
public _asm_func
68
+
.assume adl=1
69
+
70
+
.section .text._asm_func
71
+
.global _asm_func
72
+
.type _asm_func, @function
73
+
83
74
_asm_func:
84
75
pop hl
85
76
pop de
@@ -91,33 +82,29 @@ Below is an example C prototype followed by the assembly implementation:
91
82
pop de
92
83
93
84
ret
94
-
95
-
extern _external_func
85
+
86
+
.extern _external_func
96
87
97
88
:code:`asm_func.c`
98
89
99
90
.. code-block::
100
91
101
-
int external_func(int arg) {
92
+
int external_func(int arg)
93
+
{
102
94
printf("external_func called with %d\n", arg);
103
95
return 4321;
104
96
}
105
97
106
-
void test() {
98
+
void test(void)
99
+
{
107
100
int arg = 1234;
108
101
printf("calling asm_func with %d\n", arg);
109
102
int ret = asm_func(arg);
110
103
printf("asm_func returned %d\n", ret);
111
104
}
112
105
113
-
Preserve
114
-
^^^^^^^^
115
-
116
-
Assembly routines must preserve the :code:`IX` and :code:`SP` registers.
117
-
All other registers are free for use.
118
-
119
-
Arguments
120
-
^^^^^^^^^
106
+
ABI Arguments
107
+
^^^^^^^^^^^^^
121
108
122
109
Arguments are pushed from last to first corresponding to the C prototype.
123
110
In eZ80, 3 bytes are always pushed to the stack regardless of the actual size.
@@ -126,6 +113,9 @@ For example, if a *short* type is used, the upper byte of the value pushed on th
126
113
This table lists the locations relative to *sp* from within the called funciton.
127
114
Note that :code:`sp + [0,2]` contains the return address.
128
115
116
+
Assembly routines must preserve the :code:`IX` and :code:`SP` registers.
Copy file name to clipboardExpand all lines: docs/static/contributing.rst
+16-4Lines changed: 16 additions & 4 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -21,10 +21,16 @@ Building the CE Toolchain
21
21
Linux and macOS
22
22
~~~~~~~~~~~~~~~
23
23
24
-
Get the `ez80 LLVM compiler <https://github.com/jacobly0/llvm-project/wiki>`_.
24
+
It is usually easier to download a toolchain release which already contains the needed binaries for compiling/assembling if you are just making code modifications to the toolchain.
25
+
If you need to do everything from scratch though, the steps are below.
26
+
27
+
Download the prebuilt `ez80 LLVM compiler <https://github.com/CE-Programming/llvm-project/releases/tag/nightly>`_.
25
28
Make sure that ``ez80-clang`` and ``ez80-link`` are reachable by the system's PATH environment variable.
26
29
27
-
Get the `fasmg assembler <https://flatassembler.net/download.php>`_.
30
+
Download the prebuilt `ez80 GNU binutils <https://github.com/CE-Programming/binutils-gdb/releases/tag/nightly>`_
31
+
Make sure that ``bin`` directory is reachable by the system's PATH environment variable.
32
+
33
+
Download the `fasmg assembler <https://flatassembler.net/download.php>`_.
28
34
The download is located near the bottom of the page.
29
35
Extract the ``fasmg.x64`` executable to the same location as the compiler.
30
36
Rename it to just ``fasmg``.
@@ -51,15 +57,21 @@ This is configurable with :code:`make install PREFIX=[LOCATION]`
51
57
Windows
52
58
~~~~~~~
53
59
60
+
It is usually easier to download a toolchain release which already contains the needed binaries for compiling/assembling if you are just making code modifications to the toolchain.
61
+
If you need to do everything from scratch though, the steps are below.
62
+
54
63
Get `MSYS2 <https://www.msys2.org/>`_ and use the `MinGW64` environment.
55
64
56
65
The only required pacakge is `mingw-w64-x86_64-toolchain <https://packages.msys2.org/groups/mingw-w64-x86_64-toolchain>`_.
57
66
Make sure the ``C:\msys64\mingw64\bin`` directory is in the system's PATH environment variable.
58
67
59
-
Get the `ez80 LLVM compiler <https://github.com/jacobly0/llvm-project/wiki>`_.
68
+
Download the prebuilt `ez80 LLVM compiler <https://github.com/CE-Programming/llvm-project/releases/tag/nightly>`_.
60
69
Make sure that ``ez80-clang.exe`` and ``ez80-link.exe`` are reachable by the system's PATH environment variable.
61
70
62
-
Get the `fasmg assembler <https://flatassembler.net/download.php>`_.
71
+
Download the prebuilt `ez80 GNU binutils <https://github.com/CE-Programming/binutils-gdb/releases/tag/nightly>`_
72
+
Make sure that ``bin`` directory is reachable by the system's PATH environment variable.
73
+
74
+
Download the `fasmg assembler <https://flatassembler.net/download.php>`_.
63
75
The download is located near the bottom of the page.
64
76
Extract the ``fasmg.exe`` executable to the same location as the compiler.
0 commit comments