Skip to content

Commit

Permalink
Contributing guide changes (#18)
Browse files Browse the repository at this point in the history
* Added more contributing information

This commit added new information about how to add support for a new
instruction in the Jas assembler, however, this commit only descitbes
the changes for adding the instruction encoder reference table aka
the `insr_encode_table_t` as seen in `instruction.h` and the corri-
sponding source file

* Fixed typo and added new line

* Update CONTRIBUTING.md

This commit fixed spelling errors and beautified code example on  the instruction encoder table as well as the formatting of the explanation caption for the corresponding example code.

* Added changes to `CONTRIBUTING.md`

Squash 3 commits with similar published changes

* Corrected spelling mistakes and typos

* Added new section

This commit added a new section into the contributions guide, this
section explained the steps and implications involved to add a
instruction to the `instructions` enum after defining the struct

* Added termination symbol to markdown

This comit added the code section termination symbol to terminate
the demo code, since the termination symbol was forgotten in previous
commit number  b9e87d1

* Removed whitesapces between "**"

In markdown, if there are whitesapces before and/or after the bold
operator - `**`, the formatting will be omitted for some reason :((

* Finished adding support for new instruction section

This commit shows the final changes that has finished the 'Adding s-
upport for a new instruction to the assembler' section.

* Added 'Maintaince' section

This commit added rthe maintaince section that explained how the
maintaince works as a team in the Jas project as well as how they
can become and renouce maintainer status

* Update CONTRIBUTING.md

Added previously missing link for maintainers which was added in commit number d1e79dc

* Added section for adding new enocders

This commit added the section for explaining how to contribute
a new encoder to the Jas assembler.
  • Loading branch information
cheng-alvin authored Dec 23, 2024
1 parent 51ae5fc commit d8e7f65
Showing 1 changed file with 116 additions and 13 deletions.
129 changes: 116 additions & 13 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,7 @@ feature, please see [this](https://github.com/cheng-alvin/jas/issues).

### Getting started
For beginners and those who are new to Git and GitHub, please see [here](https://guides.github.com/activities/hello-world/)
for a quick tutorial on how to get started with Git and GitHub.

The Jas project is hosted on this Github page and does not have any official mirrors on other sites at this point,
for a quick tutorial on how to get started with Git and GitHub. The Jas project is hosted on this Github page and does not have any official mirrors on other sites at this point,
you may create a un-official mirror on other sites and hosts if you wish, but all official development will occur
here.

Expand All @@ -22,24 +20,21 @@ cd jas

For the safety of already stable code, we'll use branches (Like everyone else) to develop software and squash bugs
in parallel, before starting any development work, you must create a new branch and create a pull request with a
detailed description of your work and changes you have commited.
detailed description of your work and changes you have committed.

> Please note that branch and commit names shall be as short as possible, branch names should contain a one or
> two word overview on the changes commited and commit messages shall show the added changes in another couple
> two word overview on the changes committed and commit messages shall show the added changes in another couple
> words with details appearing in the description.
To ensure the quality of the contributed code, all pull requests must be reviewed by a maintainer (which is most
cases is me). Please direct all queries and concerns to eventide1029+jas@gmail.com as well as for any feedback
on code and contributions to the Assembler.
on code and contributions to the Assembler. [See below](https://github.com/cheng-alvin/jas/blob/contributing-guide-changes/CONTRIBUTING.md#how-does-maintaining-work)

### Building and testing
To build Jas, simply run `make` in the home or `libjas` directories (A debug binary must be built in `libjas`).
Tests can be added in the `tests` directory and built using `make tests` as well in the home directory, all C
test files will be automatically built and run. You may include the Jas testing framework [here](https://github.com/cheng-alvin/jas/blob/main/tests/test.h)

> The build and testing scripts must be successful before submitting a pull request up to the repo,
> if tests and compilation scripts fail, you must put your PR as a "draft" instead.
### Code style
Preferably, if you have `clang-format` installed on your system, you can simply run `make format` in the home
directory to *automatically* format the source files to conform to our programming style as specified in
Expand All @@ -48,15 +43,123 @@ your patch in your own coding style and have it formatted automatically when mer
just as long as the maintainers can read it, then it'll okay.

As mentioned above, a Github action will automatically run when new code is pushed onto the main branch to
automatically format the code using `clang-format`. You can ignore this behaviour by adding a `clang-format off`
and a corrisponding `clang-format on` comment in your code for small snippets that may break or cause issues
automatically format the code using `clang-format`. You can ignore this behavior by adding a `clang-format off`
and a corresponding `clang-format on` comment in your code for small snippets that may break or cause issues
down the line if formatted automatically.

### Adding support for a instruction to the assembler
A common addition for the Jas assembler, especially since how complex the Intel x64 instruction set is, is the
addition of new instructions and instruction encoder identities, which can be done by creating a instruction
encoder table, adding and/or registering the instruction encoder tables to the instruction list(s), and finally testing
and writing unit tests.

**First, define a instruction encode table:**

A instruction encoder table describes the identity of the instruction and how each instance can be encoded
in binary as well as some key meta data such as what modes the instruction support and operand extensions
etc. (Details will appear in the [`instruction.h`](https://github.com/cheng-alvin/jas/blob/main/libjas/include/instruction.h) file)
Each instruction encoder table includes *entries*, each entry defines the meta data that correspond to a certain
identity. For example, a MR identity (A identity with a m64 and r64) will be one entry and includes the
opcode, and support status in different operating modes. Below is an example of a instruction encoded in the `MR` identity and can be encoded as `FF /r` or `FA /r` when using the byte-instruction mode (More examples will be [here](https://github.com/cheng-alvin/jas/blob/main/libjas/instruction.c))


```c
#include <jas.h>

static instr_encode_table_t new_ent = {
.ident = OP_MR,
.opcode_ext = NULL,
.opcode = {0xff},
.support = MODE_SUPPORT_ALL,
.byte_instr_opcode = {0xfa},
.opcode_size = 1,
.pre = NULL,
};

// `new_ent` will be added to an array of different instruction identities.

```

> Many instructions share lots of operand encoding logic or patterns that can be encapsulated. Each operand encoding identities have a certain order of operand types, allowing code to be shared among instructions who have similar operand inputs. In Jas, we have denoted these identities as two letter codes like `MR`, `RM` or `Z` in which it corresponds to a certain combination of operands types (or classes if your fancy) within an instruction. In the end, they are mapped to a encoder function with the same name.
**Next, register the new instruction:**

Even though you have the instruction encoder table already setup, currently the assembler has no indication that
this instruction actually *exists*. Therefore, we'll need to indicate to the assembler that this instruction
actually exists and there's actually a encoder table for it somewhere in the source code. (Which we wrote in the
previous "chapter")

So, register the instruction and the instruction encoder table to the assembler, we'll add the instruction's name
in the `instructions` enum in the `instruction.h` header, the name should be prefixed with the prefix of `INSTR_`
and followed with the instruction's name as shown on the Intel manual to maintain consistency.

> Please ensure the instruction is not appended in the enum, but instead added **before** the directives section,
> otherwise the instruction you are trying to add as a *instruction* will be interpreted as an assembler directive. (All assembler directives are prefixed as `INSTR_DIR_` instead of just `INSTR_`)
After your shiny new instruction is registered to the `instructions` enum, you'll also need to register the instruction's
encoder table to the general lookup table for instructions called `instr_table`, they must be placed in a array in **the same**
order as the enum is in. This is very important since the assembler uses a lookup and uses the enum as a indexing tool
and fetch whatever table is needed.

### Adding a new encoder
Although most of the encoders used by 80% of all Intel x64 instructions, many are still unsupported and require
you to add it into the assembler manually, especially many of the specialized floating point instructions and
CPU specific stuff. All encoders live in the `libjas/encoder.c` file, to write a new encoder function, use the `DEFINE_ENCODER`
macro defined in `libjas/include/encoder.h` and providing the name of the encoder as the argument. (The name should be in
lowercase and match the naming scheme as shown on the Intel manual.) See example below:
```c
// ...
DEFINE_ENCODER(xx){
// ...
}
```
The `DEFINE_ENCODER` macro already gives developers some helper arguments such as the instruction encoder table to reference,
the operand array, more details appear in the `encoder.h` header, all "invokers" of these encoder function, including the
assembler itself will conform to this structure.
After defining a encoder that you are happy with, there is no way the assembler can have any indication of the *existence* of
this encoder and cannot be invoked. All encoders should be *appended* to the `enc_ident` enum in the `libjas/include/encoder.h`
header so that the order can match up to the encoders array in the `enc_lookup()` function.
> The `enc_ident` enum serves as a *indexer* for the `enc_lookup()` array and allows the lookup table to work properly.
### How does maintaining work?
Code in Jas should be a collaborative project, there is no way that one person will have the ability to look after
all the code in such a complicated project. Once a new block of code such as function or a new file is added, they
will be automatically assigned to the author(s) of that block. For example, a new encoder is merged into the assembler,
the people who initially wrote it will take care of the encoder's source, documentation and addressing issues. Their name(s)
and email addresses as well as relevant contact details (preferably Github username) should be added on the documentation
comment for the encoder similar to the one below:
```c
// func.h
/**
* @author example <example@example.com>
*
* ...
*/
void func();
```

All questions, concerns and general inquires related to this block of code should be directed to this maintainer,
he or she should also review any related PRs and keep in constant communication with other maintainers and the
contributors.

> If you do contribute some code and **do not wish** to look after it long-term as a maintainer (Which is 100% okay)
> you may drop support for it at anytime, just drop a email to eventide1029@gmail.com and I (Alvin) will be keen to do my best to look after it.
#### Becoming a maintainer
Becoming a maintainer is easy! Everyone can do it! It's a great way to contribute to the community and help out
with the constant stream of issues. To become a maintainer just drop in a quick email to me (Alvin) eventide1029@gmail.com
and I'll be happy to let you look after that portion of code.

### What to remember before submitting a PR
Once you have completed your work, remember to submit pull requests that are organised and have a clear sense of
Once you have completed your work, remember to submit pull requests that are organized and have a clear sense of
purpose, any change from one line of code to a whole file is okay, it just has to have a purpose and a clear
reason to be merged upstream. (but also remember to try and keep it small) Speaking of size, please also ensure
that you properly and logically organise banches and pull requests, if changes don't seem to fit in one pull
that you properly and logically organize branches and pull requests, if changes don't seem to fit in one pull
request logically, feel free to submit multiple, as long as it makes sense logically.

### What now?
Expand Down

0 comments on commit d8e7f65

Please sign in to comment.