EXPERIMENTAL repository for ARM7TDMI single-step tests
These tests are generated from fleroviux's excellent NanoBoyAdvance. Any errors in the test are likely errors in my code, not in NBA. Thanks to fleroviux for letting me use NBA for this! I will link both the original repository and my fork for creating these tests, in the near future.
You must run transcode_json.py after pulling the tests. This will translate the .json.bin format into .json format to easily work with. If you wish to use the binary representation, the .py file should document it fairly clearly, it's a very simple format.
These LIKELY have bugs. Until tested, don't be surprised if you get a wrong result. This is normal for releasing these tests.
These tests currently consist of 20,000 tests per .json file, each one testing a category of encoding. There may be holes or inaccuracies. Only ARM is covered, THUMB will come soon.
Each test has a list with 20000 entries that look like this (this is from hw_data_transfer_register.json):
{
"initial": {
"R": [
4172568239,
3218885584,
3611667212,
1565924574,
126631669,
898680852,
2152366193,
3510576945,
2585370008,
2084998222,
1710718908,
921484554,
857686631,
4076630577,
496381836,
3076961312
],
"R_fiq": [
1729278480,
3279118443,
1296478502,
1311475728,
2093184835,
617130518,
3124009755
],
"R_svc": [
1848569204,
3393792212
],
"R_abt": [
2644803584,
3237205884
],
"R_irq": [
4028872293,
1667487871
],
"R_und": [
1540154790,
1437581195
],
"CPSR": 805306395,
"SPSR": [
268435671,
3758096403,
1879048400,
268435483,
268435667,
805306512
],
"pipeline": [
1887645885,
10559586
]
},
"final": {
"R": [
4172568239,
3218885584,
3611667212,
1565924574,
126631669,
898680852,
2152366193,
3510576945,
2585370008,
2084998222,
1710718908,
921484554,
857686631,
0,
0,
3076961320
],
"R_fiq": [
1729278480,
3279118443,
1296478502,
1311475728,
2093184835,
617130518,
3124009755
],
"R_svc": [
1848569204,
3393792212
],
"R_abt": [
2644803584,
3237205884
],
"R_irq": [
4028872293,
1667487871
],
"R_und": [
4076630577,
496381836
],
"CPSR": 805306395,
"SPSR": [
0,
3758096403,
1879048400,
268435483,
268435667,
805306512
],
"pipeline": [
10629219,
10698852
]
},
"transactions": [
{
"kind": 0,
"size": 4,
"addr": 3076961312,
"data": 10629219,
"cycle": 1,
"access": 12,
},
{
"kind": 0,
"size": 4,
"addr": 3076961316,
"data": 10698852,
"cycle": 2,
"access": 12,
}
],
"opcode": 1887645885,
"base_addr": 3076961306
},
Is the location in RAM where opcode is located. Just the base address of the test.
They contain the initial and final state of all relevant registers in the CPU. Initial is what the CPU is set to before executing the instruction, and final is what all the same registers contain afterward.
- R: R0-R15
- R_fiq: R8-R14 banked for FIQ
- R_svc, R_abt, R_irq, R_und: R13-R14 banked for svc, abt, IRQ, and und.
- CPSR register
- SPSR registers in this order: fiq, svc, abt, irq, und
- pipeline: The contents of the instruction pipeline, in order
Are memory transactions.
"kind": 0,
"size": 4,
"addr": 3076961316,
"data": 10698852,
"cycle": 2,
"access": 12
- kind is 0 for an instruction read, 1 for a general read, and 2 for a write
- size is in bytes. so 1 = 1 byte, 2 = 16 bits, 4 = 32 bits.
- addr is the address
- data is the data
- cycle is the cycle number this transaction happened on (experimental, I'm not sure if I instrumented NBA correctly for this number)
- access is the access mask provided by NanoBoyAdvance. It is made by ORing these values together:
enum Access {
Nonsequential = 0,
Sequential = 1,
Code = 2,
Dma = 4,
Lock = 8
};
The opcode is the opcode.
Opcodes are loaded into the pipeline from the initial state, and R15 is set to the address of opcode 2 (+8 from the about-to-execute instruction, ot +4 for THUMB).
The CPU is set up in this way, and runs 1 instruction.
When your CPU issues a read or write, you should look it up in the list of transactions and compare it. You should return the included data if possible. This is for data reads; for instruction reads, we return the opcode if it's the base address, or just the address that was requested.
In pseudocode that looks something like this...
def read(addr, is_code):
if not is_code:
return lookup_transaction(addr)
if (addr == test.base_addr):
return test.opcode;
else:
return addr;
- Some illegal edge cases (which can't even be produced by assembler) where write-back register is r15 and destination register is r15, may not have perfectly correct behavior
- The tests do not properly restrict read and write alignment, other than instructions. Let me know if it's important to change this
- The tests treat RAM as a 32-bit flat space with no memory-mapped registers. Unless you want to allocate 4GB RAM, I suggest you use our transaction-based method.
- The tests may have bugs, this is an in-development release v0.1
- There may be issues with the tests we don't know yet.
- As of yet, the correct number of cycles and transactions happening on the correct cycle are not recorded. The correct order is.
I hope you find it useful!