Data space¶
Contents
Todo
document UAS
Introduction¶
Data segment of the falcon is inside the microcontroller itself. Its size can be determined by looking at UC_CAPS register, bits 9-16 shifted left by 8.
The segment has byte-oriented addressing and can be accessed in units of 8, 16, or 32 bits. Unaligned accesses are not supported and cause botched reads or writes.
Multi-byte quantities are stored as little-endian.
The stack¶
The stack is also stored in data segment. Stack pointer is stored in $sp special register and is always aligned to 4 bytes. Stack grows downwards, with $sp pointing at the last pushed value. The low 2 bits of $sp and bits higher than what’s needed to span the data space are forced to 0.
Pseudocode conventions¶
sz, for sized instructions, is the selected size of operation: 8, 16, or 32.
LD(size, address) returns the contents of size-bit quantity in data segment at specified address:
int LD(size, addr) {
if (size == 32) {
addr &= ~3;
return D[addr] | D[addr + 1] << 8 | D[addr + 2] << 16 | D[addr + 3] << 24;
} else if (size == 16) {
addr &= ~1;
return D[addr] | D[addr + 1] << 8;
} else { // size == 8
return D[addr];
}
}
ST(size, address, value) stores the given size-bit value to data segment:
void ST(size, addr, val) {
if (size == 32) {
if (addr & 1) { // fuck up the written datum as penalty for unaligned access.
val = (val & 0xff) << (addr & 3) * 8;
} else if (addr & 2) {
val = (val & 0xffff) << (addr & 3) * 8;
}
addr &= ~3;
D[addr] = val;
D[addr + 1] = val >> 8;
D[addr + 2] = val >> 16;
D[addr + 3] = val >> 24;
} else if (size == 16) {
if (addr & 1) {
val = (val & 0xff) << (addr & 1) * 8;
}
addr &= ~1;
D[addr] = val;
D[addr + 1] = val >> 8;
} else { // size == 8
D[addr] = val;
}
}
Load: ld¶
Loads 8-bit, 16-bit or 32-bit quantity from data segment to register.
- Instructions:
Name Description Subopcode - normal Subopcode - with $sp ld Load a value from data segment 8 0 - Instruction class:
- sized
- Operands:
- DST, BASE, IDX
- Forms:
Form Opcode R1, R2, I8 10 R2, $sp, I8 34 R2, $sp, R1 3a R3, R2, R1 3c - Immediates:
- zero-extended
- Operation:
DST = LD(sz, BASE + IDX * (sz/8));
Store: st¶
Stores 8-bit, 16-bit or 32-bit quantity from register to data segment.
- Instructions:
Name Description Subopcode - normal Subopcode - with $sp st Store a value to data segment 0 1 - Instruction class:
- sized
- Operands:
- BASE, IDX, SRC
- Forms:
Form Opcode R2, I8, R1 00 $sp, I8, R2 30 R2, 0, R1 38 $sp, R1, R2 38 - Immediates:
- zero-extended
- Operation:
ST(sz, BASE + IDX * (sz/8), SRC);
Push onto stack: push¶
Decrements $sp by 4, then stores a 32-bit value at top of the stack.
- Instructions:
Name Description Subopcode push Push a value onto stack 0 - Instruction class:
- unsized
- Operands:
- SRC
- Forms:
Form Opcode R2 f9 - Operation:
$sp -= 4; ST(32, $sp, SRC);
Pop from stack: pop¶
Loads 32-bit value from top of the stack, then incrments $sp by 4.
- Instructions:
Name Description Subopcode pop Pops a value from the stack 0 - Instruction class:
- unsized
- Operands:
- DST
- Forms:
Form Opcode R2 f2 - Operation:
DST = LD(32, $sp); $sp += 4;
Adjust stack pointer: add¶
Adds a value to the stack pointer.
- Instructions:
Name Description Subopcode - opcodes f4, f5 Subopcode - opcode f9 add Add a value to the stack pointer. 30 1 - Instruction class:
- unsized
- Operands:
- DST, SRC
- Forms:
Form Opcode $sp, I8 f4 $sp, I16 f5 $sp, R2 f9 - Immediates:
- sign-extended
- Operation:
$sp += SRC;
Accessing data segment through IO¶
On v3+, the data segment is accessible through normal IO space through index/data reg pairs. The number of available index/data pairs is accessible by UC_CAPS2 register. This number is equal to 4 on PDAEMON, 1 on other engines:
- MMIO 0x1c0 + i * 8 / I[0x07000 + i * 0x200]: DATA_INDEX
Selects the place in D[] accessed by DATA reg. Bits:
- bits 2-15: bits 2-15 of the data address to poke
- bit 24: write autoincrement flag: if set, every write to corresponding DATA register increments the address by 4
- bit 25: read autoincrement flag: like 24, but for reads
- MMIO 0x1c4 + i * 8 / I[0x07100 + i * 0x200]: DATA
- Writes execute ST(32, DATA_INDEX & 0xfffc, value); and increment the address if write autoincrement is enabled. Reads return the result of LD(32, DATA_INDEX & 0xfffc); and increment if read autoincrement is enabled.
i should be less than DATA_PORTS value from UC_CAPS2 register.
On v0, the data segment is instead accessible through the high falcon MMIO range, see v0 code/data upload registers for details.