## Using r2 with 8051

**Features**

* [x] Disassembler
* [x] Assembler
* [x] Emulation (esil)
* [x] Basic address space mapping

**Untested**

* [ ] Debugger

**Missing**

* [ ] Full emulation of memory-mapped registers
* [ ] Memory banking for address spaces > 64K
* [ ] Advanced analysis like local variables, function parameters ..
* [ ] More predefined CPU models

### r2 configuration

Set architecture to 8051:

```console
$ r2 -a 8051
```

Set cpu to desired model:

`e asm.cpu = ?`

After changing the cpu model, run 'aei' to initialize/reset the registers and mapped memory. For example:

```
e asm.cpu = 8051-generic
aei
```

### Address spaces and memory mapping

Pseudo-registers are used to control how r2 emulates the multiple address
spaces of the 8051. The registers hold the base address where the 8051 memory
area is located in r2 address space.

|register|address space|comment|
|--|--|--|
|_code|CODE|Program memory. Typically located at 0.|
|_idata|IDATA|256 bytes of internal RAM.|
|_sfr|SFR|128 bytes for special function registers. _sfr is the base address. Registers start at_sfr+0x80.|
|_xdata|XDATA|64K of external RAM.|
|_pdata|PDATA, XREG|MSB of address of 256-byte page in XDATA accessed with 'movx @Ri' op codes.|

The registers are initialized based on the selected CPU. See command
'e asm.cpu=?'.

The registers can be viewed and modified with the 'ar' command. When modifying
the pseudo-registers or updating 'asm.cpu', memory will be (re)allocated
automatically when the analyzer is invoked the next time (e.g. during 'aei').
Use the 'om' command to see the list of allocated memory blocks.

```console
[0x00000000]> e asm.cpu=8051.generic
[0x00000000]> aei
[0x00000000]> om
 4 fd: 6 +0x00000000 0x00000000 - 0x0000ffff -rwx
 3 fd: 5 +0x00000000 0x20000000 - 0x2000ffff -rw- xdata
 2 fd: 4 +0x00000000 0x10000180 - 0x100001ff -rw- sfr
 1 fd: 3 +0x00000000 0x10000000 - 0x100000ff -rw- idata
```

Analysis and emulation rely on the address mapping. Setup the pseudo-registers
before running analysis, or rerun analysis after updating pseudo-registers.

Address spaces can overlap in r2 memory. This allows emulating 8051 variants
that mirror IDATA and SFR into XDATA, or have shared XDATA and CODE address
spaces.

For example, the CC2430 from Texas Instruments maps SFR to 0xDF80 and IDATA to
0xFF00 in XDATA memory space. In r2 this can be setup with:

```
ar _sfr = _xdata + 0xdf00
ar _idata = _xdata + 0xff00
```

For overlapping areas, r2 will prioritize smaller memory blocks over larger ones.
For example, if IDATA is mapped into XDATA, all r2 operations will use IDATA in
the overlapping addresses. If you want to use XDATA instead, you can delete the
offending map with the command 'om-'. See 'om?'for more information.

For using emulation with overlapping code and RAM spaces, the r2 memory holding
the firmware must allow write access. This is best achieved with the command
'omf 4 rwx', with 4 being the id of the firmware file's IO map entry. See 'om?'
for more information.

Some 8051 variants use memory banking to address memory spaces larger than 64K.
Currently, memory banking is not supported by r2.

### Tips & tricks

Use pseudo-registers in r2 commands to calculate addresses. For example:

Hex dump of all special function registers:

`px @ _sfr`

Write a value to a location in external RAM

`wx deadbeef @ _xdata + 0x1234`

Set a flag for a variable stored at 0x20 in internal RAM:

`f sym.secret @ _idata + 0x20`

### Adding support for new 8051 variants

Follow these steps to add support for new 8051 variants to r2.

1. Clone latest version of radare2
2. In '/libr/anal/p/anal_8051.c' add a new entry to array 'cpu_models[]' to define a name and a memory mapping. The name of the last entry in array must be NULL
3. In 'libr/asm/p/asm_8051.c' append entry with the same name to '.cpus' attribute
4. Compile, test your addition, and submit a pull request
