* Initial
This commit is contained in:
@@ -0,0 +1,187 @@
|
||||
# API Reference
|
||||
|
||||
ReviveSparc provides a C API for embedding the SPARC emulator in other projects.
|
||||
|
||||
## Core API
|
||||
|
||||
### Initialization
|
||||
|
||||
```c
|
||||
#include <revivesparc.h>
|
||||
|
||||
// Create a new SPARC CPU instance
|
||||
sparc_t *sparc_new(sparc_isa_t isa);
|
||||
```
|
||||
|
||||
Parameters:
|
||||
- `isa`: `SPARC_V9` for 64-bit mode, `SPARC_V8` for 32-bit compatibility mode
|
||||
|
||||
Returns: Pointer to a new SPARC instance, or NULL on failure.
|
||||
|
||||
```c
|
||||
// Create with custom configuration
|
||||
sparc_t *sparc_new_with_config(const sparc_config_t *config);
|
||||
```
|
||||
|
||||
```c
|
||||
// Free a SPARC instance
|
||||
void sparc_free(sparc_t *cpu);
|
||||
```
|
||||
|
||||
### Loading Programs
|
||||
|
||||
```c
|
||||
// Load an ELF file into memory
|
||||
int sparc_load_elf(sparc_t *cpu, const char *path);
|
||||
|
||||
// Load a flat binary into memory at a specific address
|
||||
int sparc_load_binary(sparc_t *cpu, const char *path, uint64_t addr);
|
||||
|
||||
// Load a file into memory at a specific offset
|
||||
int sparc_load_file(sparc_t *cpu, const char *path, uint64_t addr);
|
||||
```
|
||||
|
||||
All load functions return 0 on success, -1 on error.
|
||||
|
||||
### Execution Control
|
||||
|
||||
```c
|
||||
// Reset the CPU to initial state
|
||||
void sparc_reset(sparc_t *cpu);
|
||||
|
||||
// Run for a specified number of instructions
|
||||
uint64_t sparc_run(sparc_t *cpu, uint64_t num_insts);
|
||||
|
||||
// Run until a breakpoint is hit
|
||||
uint64_t sparc_run_until_break(sparc_t *cpu);
|
||||
|
||||
// Step a single instruction
|
||||
int sparc_step(sparc_t *cpu);
|
||||
|
||||
// Stop execution (called from interrupt handler)
|
||||
void sparc_stop(sparc_t *cpu);
|
||||
```
|
||||
|
||||
Returns the actual number of instructions executed.
|
||||
|
||||
### Register Access
|
||||
|
||||
```c
|
||||
// Read/write general-purpose registers
|
||||
uint64_t sparc_get_gpr(sparc_t *cpu, int reg);
|
||||
void sparc_set_gpr(sparc_t *cpu, int reg, uint64_t val);
|
||||
|
||||
// Read/write special registers
|
||||
uint64_t sparc_get_pc(sparc_t *cpu);
|
||||
void sparc_set_pc(sparc_t *cpu, uint64_t val);
|
||||
|
||||
uint64_t sparc_get_npc(sparc_t *cpu);
|
||||
void sparc_set_npc(sparc_t *cpu, uint64_t val);
|
||||
|
||||
// Floating-point registers
|
||||
double sparc_get_fpr(sparc_t *cpu, int reg);
|
||||
void sparc_set_fpr(sparc_t *cpu, int reg, double val);
|
||||
|
||||
// Privileged registers
|
||||
uint64_t sparc_get_priv(sparc_t *cpu, sparc_priv_reg_t reg);
|
||||
void sparc_set_priv(sparc_t *cpu, sparc_priv_reg_t reg, uint64_t val);
|
||||
```
|
||||
|
||||
### Memory Access
|
||||
|
||||
```c
|
||||
// Direct memory access (bypasses MMU)
|
||||
int sparc_mem_write(sparc_t *cpu, uint64_t addr, const void *buf, size_t len);
|
||||
int sparc_mem_read(sparc_t *cpu, uint64_t addr, void *buf, size_t len);
|
||||
|
||||
// Virtual memory access (through MMU)
|
||||
int sparc_virt_write(sparc_t *cpu, uint64_t addr, const void *buf, size_t len);
|
||||
int sparc_virt_read(sparc_t *cpu, uint64_t addr, void *buf, size_t len);
|
||||
```
|
||||
|
||||
Returns the number of bytes read/written, or -1 on error.
|
||||
|
||||
### Debugging
|
||||
|
||||
```c
|
||||
// Set a breakpoint at a virtual address
|
||||
int sparc_breakpoint_set(sparc_t *cpu, uint64_t addr);
|
||||
|
||||
// Clear a breakpoint
|
||||
int sparc_breakpoint_clear(sparc_t *cpu, uint64_t addr);
|
||||
|
||||
// Get disassembly of an instruction
|
||||
const char *sparc_disassemble(sparc_t *cpu, uint64_t addr);
|
||||
|
||||
// Set tracing level
|
||||
void sparc_set_trace(sparc_t *cpu, int level);
|
||||
```
|
||||
|
||||
## Configuration Structures
|
||||
|
||||
```c
|
||||
typedef struct {
|
||||
int num_cores; // Number of cores (1-8)
|
||||
int threads_per_core; // Threads per core (1-4)
|
||||
sparc_mem_t memory_model; // TSO, PSO, or RMO
|
||||
sparc_sched_t sched_mode; // Fine or coarse-grained
|
||||
uint64_t mem_size; // Main memory size in bytes
|
||||
int l1i_size; // L1 I-cache size in bytes
|
||||
int l1d_size; // L1 D-cache size in bytes
|
||||
int l2_size; // L2 cache size in bytes
|
||||
int num_windows; // Number of register windows (8-32)
|
||||
} sparc_config_t;
|
||||
```
|
||||
|
||||
## Error Handling
|
||||
|
||||
Most functions return 0 on success and -1 on error. Detailed error information can be retrieved:
|
||||
|
||||
```c
|
||||
// Get the last error message
|
||||
const char *sparc_error(sparc_t *cpu);
|
||||
|
||||
// Get the last error code
|
||||
int sparc_errno(sparc_t *cpu);
|
||||
```
|
||||
|
||||
## Example: Embedded Emulator
|
||||
|
||||
```c
|
||||
#include <stdio.h>
|
||||
#include <revivesparc.h>
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
sparc_t *cpu = sparc_new(SPARC_V9);
|
||||
if (!cpu) {
|
||||
fprintf(stderr, "Failed to create CPU\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
sparc_config_t config = {
|
||||
.num_cores = 1,
|
||||
.mem_size = 256 * 1024 * 1024,
|
||||
.memory_model = MEM_TSO
|
||||
};
|
||||
sparc_configure(cpu, &config);
|
||||
|
||||
if (sparc_load_elf(cpu, argv[1]) != 0) {
|
||||
fprintf(stderr, "Failed to load ELF: %s\n", sparc_error(cpu));
|
||||
return 1;
|
||||
}
|
||||
|
||||
sparc_reset(cpu);
|
||||
uint64_t insts = sparc_run(cpu, 1000000);
|
||||
printf("Executed %lu instructions\n", insts);
|
||||
printf("Final PC: 0x%lx\n", sparc_get_pc(cpu));
|
||||
|
||||
sparc_free(cpu);
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
Compile with:
|
||||
|
||||
```bash
|
||||
cc -o myemu myemu.c -lrevivesparc
|
||||
```
|
||||
Reference in New Issue
Block a user