Compare commits
No commits in common. "47d226cf3605396a7f995e9ad12e76907a328c7e" and "c248a7507c07862d45dc15a61767ee34a8786c40" have entirely different histories.
47d226cf36
...
c248a7507c
9 changed files with 232 additions and 202 deletions
|
@ -581,7 +581,7 @@ static int gen_ins_write_state(
|
|||
break;
|
||||
case GMR_OFFSET:
|
||||
ins.offset = state->offset;
|
||||
reftype = REF_MIPS_PC16;
|
||||
reftype = REF_MIPS_16;
|
||||
break;
|
||||
case GMR_OFFSET_BASE:
|
||||
ins.offset = state->offset;
|
||||
|
|
25
mld/link.c
25
mld/link.c
|
@ -8,9 +8,9 @@
|
|||
#include <sys/stat.h>
|
||||
#include <melf.h>
|
||||
#include <fcntl.h>
|
||||
#include <mips32.h>
|
||||
|
||||
#include "link.h"
|
||||
#include "mips.h"
|
||||
|
||||
static int load_objects(struct linker *linker)
|
||||
{
|
||||
|
@ -443,7 +443,7 @@ static int relocate_instruction_rela(struct linker *linker,
|
|||
uint32_t sym_vaddr = B32(new_sym->st_value);
|
||||
uint32_t *ins_raw = (uint32_t *) &seg->bytes[off];
|
||||
|
||||
union mips32_instruction ins;
|
||||
union mips_instruction_data ins;
|
||||
ins.raw = B32(*ins_raw);
|
||||
|
||||
uint32_t ins_vaddr = seg->new_vaddr + off;
|
||||
|
@ -565,6 +565,20 @@ static void update_offsets(struct linker *linker)
|
|||
// sections
|
||||
for (uint32_t i = 0; i < linker->segments.len; i++) {
|
||||
struct segment_table_entry *ent = &linker->segments.entries[i];
|
||||
|
||||
// section padding
|
||||
{
|
||||
uint32_t m = ptr % SEC_ALIGN;
|
||||
if (m) {
|
||||
uint32_t add = SEC_ALIGN - m;
|
||||
ptr += add;
|
||||
ent->off = ptr;
|
||||
ent->padding = add;
|
||||
} else {
|
||||
ent->padding = 0;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t idx = i + 1;
|
||||
uint32_t size = segtab_ent_size(ent);
|
||||
linker->phdr[i].p_offset = B32(ptr);
|
||||
|
@ -620,6 +634,13 @@ static int write_file(struct linker *linker)
|
|||
// sections
|
||||
for (uint32_t i = 0; i < linker->segments.len; i++) {
|
||||
struct segment_table_entry *ent = &linker->segments.entries[i];
|
||||
// section padding
|
||||
{
|
||||
for (uint32_t i = 0; i < ent->padding; i++) {
|
||||
uint8_t zero = 0;
|
||||
res |= fwrite(&zero, 1, 1, out);
|
||||
}
|
||||
}
|
||||
for (uint32_t j = 0; j < ent->len; j++) {
|
||||
struct segment *seg = ent->parts[j];
|
||||
res |= fwrite(seg->bytes, 1, seg->size, out);
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
#include <linux/limits.h>
|
||||
#include <mlimits.h>
|
||||
#include <mips.h>
|
||||
#include <merror.h>
|
||||
#include <stdint.h>
|
||||
#include <elf.h>
|
||||
|
@ -173,6 +174,8 @@ struct segment_table_entry {
|
|||
uint32_t vaddr;
|
||||
// weak segment pointers. we do not own these!!!
|
||||
struct segment **parts;
|
||||
// section padding
|
||||
uint32_t padding;
|
||||
};
|
||||
|
||||
int segtab_ent_init(struct segment_table_entry *ent);
|
||||
|
@ -221,6 +224,7 @@ struct object {
|
|||
// program table
|
||||
Elf32_Phdr *phdr;
|
||||
size_t phdr_len;
|
||||
bool phdr_local; // if phdr was created though malloc
|
||||
|
||||
// phdr <=> shdr mappings
|
||||
uint32_t *phdr_to_shdr_mapping;
|
||||
|
|
32
mld/obj.c
32
mld/obj.c
|
@ -67,7 +67,7 @@ static int load_ehdr(struct object *object)
|
|||
*/
|
||||
static int load_shdr(struct object *object)
|
||||
{
|
||||
size_t shdr_len = sizeof(Elf32_Shdr) *
|
||||
size_t shdr_len = B16(object->ehdr->e_shentsize) *
|
||||
B16(object->ehdr->e_shnum);
|
||||
size_t shdr_off = B32(object->ehdr->e_shoff);
|
||||
object->shdr = (Elf32_Shdr *) (object->mapped + shdr_off);
|
||||
|
@ -105,6 +105,7 @@ static int create_phdr(struct object *object)
|
|||
|
||||
object->phdr = phdr;
|
||||
object->phdr_len = entries;
|
||||
object->phdr_local = true;
|
||||
|
||||
uint32_t *mapping = malloc(entries * sizeof(uint32_t));
|
||||
if (mapping == NULL) {
|
||||
|
@ -147,6 +148,29 @@ static int create_phdr(struct object *object)
|
|||
return M_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Map the phdr
|
||||
*/
|
||||
static int load_phdr(struct object *object)
|
||||
{
|
||||
//size_t phdr_len = B16(object->ehdr->e_phentsize) *
|
||||
// B16(object->ehdr->e_phnum);
|
||||
|
||||
//if (phdr_len < 1)
|
||||
return create_phdr(object);
|
||||
|
||||
//size_t phdr_off = B32(object->ehdr->e_phoff);
|
||||
//object->phdr = (Elf32_Phdr *) (object->mapped + phdr_off);
|
||||
//object->phdr_len = B16(object->ehdr->e_phnum);
|
||||
|
||||
//if (BOUND_CHK(object, phdr_len, phdr_off)) {
|
||||
// ERROR("cannot read phdr");
|
||||
// return M_ERROR;
|
||||
//}
|
||||
|
||||
//return M_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the strtabs
|
||||
*/
|
||||
|
@ -334,7 +358,7 @@ int object_load(struct object *object, char *path, uint32_t index)
|
|||
object->mapped = NULL;
|
||||
object->name = path;
|
||||
object->index = index;
|
||||
object->phdr = NULL;
|
||||
object->phdr_local = false;
|
||||
object->phdr_to_shdr_mapping = NULL;
|
||||
|
||||
/** load the file */
|
||||
|
@ -350,7 +374,7 @@ int object_load(struct object *object, char *path, uint32_t index)
|
|||
return M_ERROR;
|
||||
|
||||
/* phdr */
|
||||
if (create_phdr(object))
|
||||
if (load_phdr(object))
|
||||
return M_ERROR;
|
||||
|
||||
/* strtabs */
|
||||
|
@ -380,7 +404,7 @@ void object_free(struct object *obj)
|
|||
free(obj->strtabs);
|
||||
if (obj->segments != NULL)
|
||||
free(obj->segments);
|
||||
if (obj->phdr != NULL)
|
||||
if (obj->phdr_local)
|
||||
free(obj->phdr);
|
||||
if (obj->phdr_to_shdr_mapping)
|
||||
free(obj->phdr_to_shdr_mapping);
|
||||
|
|
210
msim/ins.c
210
msim/ins.c
|
@ -1,8 +1,8 @@
|
|||
#include <mips.h>
|
||||
#include <melf.h>
|
||||
#include <stdint.h>
|
||||
#include <unistd.h>
|
||||
#include <merror.h>
|
||||
#include <mips32r6.h>
|
||||
#include "sim.h"
|
||||
|
||||
/* sign extension */
|
||||
|
@ -33,22 +33,22 @@ static void sim_delay_slot(struct simulator *sim)
|
|||
return;
|
||||
|
||||
uint32_t ins = * (uint32_t *) (uintptr_t) sim->pc;
|
||||
union mips32_instruction data = { .raw = B32(ins) };
|
||||
union mips_instruction_data data = { .raw = B32(ins) };
|
||||
sim->pc += 4;
|
||||
|
||||
switch (data.op) {
|
||||
case MIPS32R6_OP_REGIMM:
|
||||
case MIPS32R6_OP_J:
|
||||
case MIPS32R6_OP_JAL:
|
||||
case MIPS32R6_OP_JALX:
|
||||
case MIPS32R6_OP_BEQ:
|
||||
case MIPS32R6_OP_BEQL:
|
||||
case MIPS32R6_OP_BNE:
|
||||
case MIPS32R6_OP_BNEL:
|
||||
case MIPS32R6_OP_BGTZ:
|
||||
case MIPS32R6_OP_BGTZL:
|
||||
case MIPS32R6_OP_BLEZ:
|
||||
case MIPS32R6_OP_BLEZL:
|
||||
case MIPS_OP_REGIMM:
|
||||
case MIPS_OP_J:
|
||||
case MIPS_OP_JAL:
|
||||
case MIPS_OP_JALX:
|
||||
case MIPS_OP_BEQ:
|
||||
case MIPS_OP_BEQL:
|
||||
case MIPS_OP_BNE:
|
||||
case MIPS_OP_BNEL:
|
||||
case MIPS_OP_BGTZ:
|
||||
case MIPS_OP_BGTZL:
|
||||
case MIPS_OP_BLEZ:
|
||||
case MIPS_OP_BLEZL:
|
||||
sim_dump(sim, "attempted to execute jump instruction in delay"
|
||||
"slot (0b%05b)", data.op);
|
||||
default:
|
||||
|
@ -58,15 +58,15 @@ static void sim_delay_slot(struct simulator *sim)
|
|||
}
|
||||
|
||||
static void sim_ins_special_sop30(struct simulator *sim,
|
||||
union mips32_instruction ins)
|
||||
union mips_instruction_data ins)
|
||||
{
|
||||
switch (ins.shamt) {
|
||||
case MIPS32R6_SOP30_MUL:
|
||||
case MIPS_SOP30_MUL:
|
||||
sim->reg[ins.rd] = (SSE64(sim->reg[ins.rs]) *
|
||||
SSE64(sim->reg[ins.rt])) >> 0;
|
||||
break;
|
||||
|
||||
case MIPS32R6_SOP30_MUH:
|
||||
case MIPS_SOP30_MUH:
|
||||
sim->reg[ins.rd] = (SSE64(sim->reg[ins.rs]) *
|
||||
SSE64(sim->reg[ins.rt])) >> 32;
|
||||
break;
|
||||
|
@ -77,15 +77,15 @@ static void sim_ins_special_sop30(struct simulator *sim,
|
|||
}
|
||||
|
||||
static void sim_ins_special_sop31(struct simulator *sim,
|
||||
union mips32_instruction ins)
|
||||
union mips_instruction_data ins)
|
||||
{
|
||||
switch (ins.shamt) {
|
||||
case MIPS32R6_SOP31_MULU:
|
||||
case MIPS_SOP31_MULU:
|
||||
sim->reg[ins.rd] = (SE64(sim->reg[ins.rs]) *
|
||||
SE64(sim->reg[ins.rt])) >> 0;
|
||||
break;
|
||||
|
||||
case MIPS32R6_SOP31_MUHU:
|
||||
case MIPS_SOP31_MUHU:
|
||||
sim->reg[ins.rd] = (SE64(sim->reg[ins.rs]) *
|
||||
SE64(sim->reg[ins.rt])) >> 32;
|
||||
break;
|
||||
|
@ -96,15 +96,15 @@ static void sim_ins_special_sop31(struct simulator *sim,
|
|||
}
|
||||
|
||||
static void sim_ins_special_sop32(struct simulator *sim,
|
||||
union mips32_instruction ins)
|
||||
union mips_instruction_data ins)
|
||||
{
|
||||
switch (ins.shamt) {
|
||||
case MIPS32R6_SOP32_DIV:
|
||||
case MIPS_SOP32_DIV:
|
||||
sim->reg[ins.rd] = (signed) sim->reg[ins.rs] /
|
||||
(signed) sim->reg[ins.rt];
|
||||
break;
|
||||
|
||||
case MIPS32R6_SOP32_MOD:
|
||||
case MIPS_SOP32_MOD:
|
||||
sim->reg[ins.rd] = (signed) sim->reg[ins.rs] %
|
||||
(signed) sim->reg[ins.rt];
|
||||
break;
|
||||
|
@ -115,14 +115,14 @@ static void sim_ins_special_sop32(struct simulator *sim,
|
|||
}
|
||||
|
||||
static void sim_ins_special_sop33(struct simulator *sim,
|
||||
union mips32_instruction ins)
|
||||
union mips_instruction_data ins)
|
||||
{
|
||||
switch (ins.shamt) {
|
||||
case MIPS32R6_SOP33_DIVU:
|
||||
case MIPS_SOP33_DIVU:
|
||||
sim->reg[ins.rd] = sim->reg[ins.rs] / sim->reg[ins.rt];
|
||||
break;
|
||||
|
||||
case MIPS32R6_SOP33_MODU:
|
||||
case MIPS_SOP33_MODU:
|
||||
sim->reg[ins.rd] = sim->reg[ins.rs] % sim->reg[ins.rt];
|
||||
break;
|
||||
|
||||
|
@ -132,124 +132,124 @@ static void sim_ins_special_sop33(struct simulator *sim,
|
|||
}
|
||||
|
||||
static void sim_ins_special(struct simulator *sim,
|
||||
union mips32_instruction ins)
|
||||
union mips_instruction_data ins)
|
||||
{
|
||||
switch (ins.funct) {
|
||||
case MIPS32R6_FUNCT_ADD:
|
||||
case MIPS_FUNCT_ADD:
|
||||
// TODO: trap on overflow
|
||||
sim->reg[ins.rd] = sim->reg[ins.rs] + sim->reg[ins.rt];
|
||||
break;
|
||||
|
||||
case MIPS32R6_FUNCT_ADDU:
|
||||
case MIPS_FUNCT_ADDU:
|
||||
sim->reg[ins.rd] = sim->reg[ins.rs] + sim->reg[ins.rt];
|
||||
break;
|
||||
|
||||
case MIPS32R6_FUNCT_AND:
|
||||
case MIPS_FUNCT_AND:
|
||||
sim->reg[ins.rd] = sim->reg[ins.rs] & sim->reg[ins.rt];
|
||||
break;
|
||||
|
||||
case MIPS32R6_FUNCT_SOP30:
|
||||
case MIPS_FUNCT_SOP30:
|
||||
sim_ins_special_sop30(sim, ins);
|
||||
break;
|
||||
|
||||
case MIPS32R6_FUNCT_SOP31:
|
||||
case MIPS_FUNCT_SOP31:
|
||||
sim_ins_special_sop31(sim, ins);
|
||||
break;
|
||||
|
||||
case MIPS32R6_FUNCT_SOP32:
|
||||
case MIPS_FUNCT_SOP32:
|
||||
sim_ins_special_sop32(sim, ins);
|
||||
break;
|
||||
|
||||
case MIPS32R6_FUNCT_SOP33:
|
||||
case MIPS_FUNCT_SOP33:
|
||||
sim_ins_special_sop33(sim, ins);
|
||||
break;
|
||||
|
||||
case MIPS32R6_FUNCT_JALR:
|
||||
case MIPS_FUNCT_JALR:
|
||||
sim->reg[ins.rd] = sim->pc + 4;
|
||||
/* fall through */
|
||||
case MIPS32R6_FUNCT_JR:
|
||||
case MIPS_FUNCT_JR:
|
||||
sim_delay_slot(sim);
|
||||
sim->pc = sim->reg[ins.rs];
|
||||
break;
|
||||
|
||||
case MIPS32R6_FUNCT_MFHI:
|
||||
case MIPS_FUNCT_MFHI:
|
||||
sim->reg[ins.rd] = sim->hi;
|
||||
break;
|
||||
|
||||
case MIPS32R6_FUNCT_MFLO:
|
||||
case MIPS_FUNCT_MFLO:
|
||||
sim->reg[ins.rd] = sim->low;
|
||||
break;
|
||||
|
||||
case MIPS32R6_FUNCT_MTHI:
|
||||
case MIPS_FUNCT_MTHI:
|
||||
sim->hi = sim->reg[ins.rd];
|
||||
break;
|
||||
|
||||
case MIPS32R6_FUNCT_MTLO:
|
||||
case MIPS_FUNCT_MTLO:
|
||||
sim->low = sim->reg[ins.rd];
|
||||
break;
|
||||
|
||||
case MIPS32R6_FUNCT_SLL:
|
||||
case MIPS_FUNCT_SLL:
|
||||
sim->reg[ins.rd] = sim->reg[ins.rt] << ins.shamt;
|
||||
break;
|
||||
|
||||
case MIPS32R6_FUNCT_SLLV:
|
||||
case MIPS_FUNCT_SLLV:
|
||||
sim->reg[ins.rd] = sim->reg[ins.rt] << sim->reg[ins.rs];
|
||||
break;
|
||||
|
||||
case MIPS32R6_FUNCT_SLT:
|
||||
case MIPS_FUNCT_SLT:
|
||||
sim->reg[ins.rd] = (signed) sim->reg[ins.rs] <
|
||||
(signed) sim->reg[ins.rt] ? 1 : 0;
|
||||
break;
|
||||
|
||||
case MIPS32R6_FUNCT_SLTU:
|
||||
case MIPS_FUNCT_SLTU:
|
||||
sim->reg[ins.rd] = sim->reg[ins.rs] < sim->reg[ins.rt] ? 1 : 0;
|
||||
break;
|
||||
|
||||
case MIPS32R6_FUNCT_SRA:
|
||||
case MIPS_FUNCT_SRA:
|
||||
sim->reg[ins.rd] = (signed) sim->reg[ins.rt] >> ins.shamt;
|
||||
break;
|
||||
|
||||
case MIPS32R6_FUNCT_SRAV:
|
||||
case MIPS_FUNCT_SRAV:
|
||||
sim->reg[ins.rd] = (signed) sim->reg[ins.rt] >>
|
||||
sim->reg[ins.rs];
|
||||
break;
|
||||
|
||||
case MIPS32R6_FUNCT_SRL:
|
||||
case MIPS_FUNCT_SRL:
|
||||
sim->reg[ins.rd] = sim->reg[ins.rt] >> ins.shamt;
|
||||
break;
|
||||
|
||||
case MIPS32R6_FUNCT_SRLV:
|
||||
case MIPS_FUNCT_SRLV:
|
||||
sim->reg[ins.rd] = sim->reg[ins.rt] >> sim->reg[ins.rs];
|
||||
break;
|
||||
|
||||
case MIPS32R6_FUNCT_SUB:
|
||||
case MIPS_FUNCT_SUB:
|
||||
// TODO: trap on overflow
|
||||
sim->reg[ins.rd] = sim->reg[ins.rs] - sim->reg[ins.rt];
|
||||
break;
|
||||
|
||||
case MIPS32R6_FUNCT_SUBU:
|
||||
case MIPS_FUNCT_SUBU:
|
||||
sim->reg[ins.rd] = sim->reg[ins.rs] - sim->reg[ins.rt];
|
||||
break;
|
||||
|
||||
case MIPS32R6_FUNCT_SYSCALL:
|
||||
sim->reg[MIPS32_REG_V0] = syscall(
|
||||
sim->reg[MIPS32_REG_V0],
|
||||
sim->reg[MIPS32_REG_A0],
|
||||
sim->reg[MIPS32_REG_A1],
|
||||
sim->reg[MIPS32_REG_A2],
|
||||
sim->reg[MIPS32_REG_A3]
|
||||
case MIPS_FUNCT_SYSCALL:
|
||||
sim->reg[MIPS_REG_V0] = syscall(
|
||||
sim->reg[MIPS_REG_V0],
|
||||
sim->reg[MIPS_REG_A0],
|
||||
sim->reg[MIPS_REG_A1],
|
||||
sim->reg[MIPS_REG_A2],
|
||||
sim->reg[MIPS_REG_A3]
|
||||
);
|
||||
break;
|
||||
|
||||
case MIPS32R6_FUNCT_OR:
|
||||
case MIPS_FUNCT_OR:
|
||||
sim->reg[ins.rd] = sim->reg[ins.rs] | sim->reg[ins.rt];
|
||||
break;
|
||||
|
||||
case MIPS32R6_FUNCT_NOR:
|
||||
case MIPS_FUNCT_NOR:
|
||||
sim->reg[ins.rd] = !(sim->reg[ins.rs] | sim->reg[ins.rt]);
|
||||
break;
|
||||
|
||||
case MIPS32R6_FUNCT_XOR:
|
||||
case MIPS_FUNCT_XOR:
|
||||
sim->reg[ins.rd] = sim->reg[ins.rs] ^ sim->reg[ins.rt];
|
||||
break;
|
||||
|
||||
|
@ -259,28 +259,28 @@ static void sim_ins_special(struct simulator *sim,
|
|||
}
|
||||
|
||||
static void sim_ins_regimm(struct simulator *sim,
|
||||
union mips32_instruction ins)
|
||||
union mips_instruction_data ins)
|
||||
{
|
||||
uint32_t pc = sim->pc;
|
||||
|
||||
switch (ins.bfunct) {
|
||||
case MIPS32R6_FUNCT_BGEZAL:
|
||||
case MIPS32R6_FUNCT_BGEZALL:
|
||||
sim->reg[MIPS32_REG_RA] = sim->pc + 4;
|
||||
case MIPS_FUNCT_BGEZAL:
|
||||
case MIPS_FUNCT_BGEZALL:
|
||||
sim->reg[MIPS_REG_RA] = sim->pc + 4;
|
||||
/* fall through */
|
||||
case MIPS32R6_FUNCT_BGEZ:
|
||||
case MIPS32R6_FUNCT_BGEZL:
|
||||
case MIPS_FUNCT_BGEZ:
|
||||
case MIPS_FUNCT_BGEZL:
|
||||
sim_delay_slot(sim);
|
||||
if ((signed) sim->reg[ins.rs] >= 0)
|
||||
sim->pc = pc + SSE(ins.offset, 2);
|
||||
break;
|
||||
|
||||
case MIPS32R6_FUNCT_BLTZAL:
|
||||
case MIPS32R6_FUNCT_BLTZALL:
|
||||
sim->reg[MIPS32_REG_RA] = sim->pc + 4;
|
||||
case MIPS_FUNCT_BLTZAL:
|
||||
case MIPS_FUNCT_BLTZALL:
|
||||
sim->reg[MIPS_REG_RA] = sim->pc + 4;
|
||||
/* fall through */
|
||||
case MIPS32R6_FUNCT_BLTZ:
|
||||
case MIPS32R6_FUNCT_BLTZL:
|
||||
case MIPS_FUNCT_BLTZ:
|
||||
case MIPS_FUNCT_BLTZL:
|
||||
sim_delay_slot(sim);
|
||||
if ((signed) sim->reg[ins.rs] < 0)
|
||||
sim->pc = pc + SSE(ins.offset, 2);
|
||||
|
@ -294,130 +294,130 @@ static void sim_ins_regimm(struct simulator *sim,
|
|||
void sim_ins(struct simulator *sim, uint32_t raw)
|
||||
{
|
||||
// get ins parts
|
||||
union mips32_instruction ins = {
|
||||
union mips_instruction_data ins = {
|
||||
.raw = B32(raw)
|
||||
};
|
||||
uint32_t pc = sim->pc;
|
||||
|
||||
// reset zero reg
|
||||
sim->reg[MIPS32_REG_ZERO] = 0;
|
||||
sim->reg[MIPS_REG_ZERO] = 0;
|
||||
|
||||
switch (ins.op) {
|
||||
case MIPS32R6_OP_SPECIAL:
|
||||
case MIPS_OP_SPECIAL:
|
||||
sim_ins_special(sim, ins);
|
||||
break;
|
||||
|
||||
case MIPS32R6_OP_REGIMM:
|
||||
case MIPS_OP_REGIMM:
|
||||
sim_ins_regimm(sim, ins);
|
||||
break;
|
||||
|
||||
case MIPS32R6_OP_ADDI:
|
||||
case MIPS_OP_ADDI:
|
||||
sim->reg[ins.rt] = (int32_t)sim->reg[ins.rs] +
|
||||
SE(ins.immd);
|
||||
break;
|
||||
|
||||
case MIPS32R6_OP_ADDIU:
|
||||
case MIPS_OP_ADDIU:
|
||||
sim->reg[ins.rt] = sim->reg[ins.rs] + SE(ins.immd);
|
||||
break;
|
||||
|
||||
case MIPS32R6_OP_ANDI:
|
||||
case MIPS_OP_ANDI:
|
||||
sim->reg[ins.rt] = sim->reg[ins.rs] & ZE(ins.immd);
|
||||
break;
|
||||
|
||||
case MIPS32R6_OP_BALC:
|
||||
sim->reg[MIPS32_REG_RA] = sim->pc;
|
||||
case MIPS_OP_BALC:
|
||||
sim->reg[MIPS_REG_RA] = sim->pc;
|
||||
/* fall through */
|
||||
case MIPS32R6_OP_BC:
|
||||
case MIPS_OP_BC:
|
||||
sim->pc += SSE(ins.offs26, 2);
|
||||
break;
|
||||
|
||||
case MIPS32R6_OP_BEQ:
|
||||
case MIPS32R6_OP_BEQL:
|
||||
case MIPS_OP_BEQ:
|
||||
case MIPS_OP_BEQL:
|
||||
sim_delay_slot(sim);
|
||||
if (sim->reg[ins.rs] == sim->reg[ins.rt])
|
||||
sim->pc = pc + SSE(ins.offset, 2);
|
||||
break;
|
||||
|
||||
case MIPS32R6_OP_BGTZ:
|
||||
case MIPS32R6_OP_BGTZL:
|
||||
case MIPS_OP_BGTZ:
|
||||
case MIPS_OP_BGTZL:
|
||||
sim_delay_slot(sim);
|
||||
if ((signed) sim->reg[ins.rs] <= 0)
|
||||
sim->pc = pc + SSE(ins.offset, 2);
|
||||
break;
|
||||
|
||||
case MIPS32R6_OP_BLEZ:
|
||||
case MIPS32R6_OP_BLEZL:
|
||||
case MIPS_OP_BLEZ:
|
||||
case MIPS_OP_BLEZL:
|
||||
sim_delay_slot(sim);
|
||||
if ((signed) sim->reg[ins.rs] <= 0)
|
||||
sim->pc = pc + SSE(ins.offset, 2);
|
||||
break;
|
||||
|
||||
case MIPS32R6_OP_BNE:
|
||||
case MIPS32R6_OP_BNEL:
|
||||
case MIPS_OP_BNE:
|
||||
case MIPS_OP_BNEL:
|
||||
sim_delay_slot(sim);
|
||||
if (sim->reg[ins.rs] != sim->reg[ins.rt])
|
||||
sim->pc = pc + SSE(ins.offset, 2);
|
||||
break;
|
||||
|
||||
case MIPS32R6_OP_JAL:
|
||||
sim->reg[MIPS32_REG_RA] = sim->pc + 4;
|
||||
case MIPS_OP_JAL:
|
||||
sim->reg[MIPS_REG_RA] = sim->pc + 4;
|
||||
/* fall through */
|
||||
case MIPS32R6_OP_J:
|
||||
case MIPS_OP_J:
|
||||
sim_delay_slot(sim);
|
||||
sim->pc &= 0xF0000000;
|
||||
sim->pc |= ins.target << 2;
|
||||
break;
|
||||
|
||||
case MIPS32R6_OP_LB:
|
||||
case MIPS_OP_LB:
|
||||
sim->reg[ins.rt] = *PTR(VADDR(sim, ins), int8_t);
|
||||
break;
|
||||
|
||||
case MIPS32R6_OP_LBU:
|
||||
case MIPS_OP_LBU:
|
||||
sim->reg[ins.rt] = *PTR(VADDR(sim, ins), uint8_t);
|
||||
break;
|
||||
|
||||
case MIPS32R6_OP_LH:
|
||||
case MIPS_OP_LH:
|
||||
sim->reg[ins.rt] = *PTR(VADDR(sim, ins), int16_t);
|
||||
break;
|
||||
|
||||
case MIPS32R6_OP_LHU:
|
||||
case MIPS_OP_LHU:
|
||||
sim->reg[ins.rt] = *PTR(VADDR(sim, ins), uint16_t);
|
||||
break;
|
||||
|
||||
case MIPS32R6_OP_LUI:
|
||||
case MIPS_OP_LUI:
|
||||
sim->reg[ins.rt] = ins.immd << 16;
|
||||
break;
|
||||
|
||||
case MIPS32R6_OP_LW:
|
||||
case MIPS_OP_LW:
|
||||
sim->reg[ins.rt] = *PTR(VADDR(sim, ins), uint32_t);
|
||||
break;
|
||||
|
||||
case MIPS32R6_OP_SB:
|
||||
case MIPS_OP_SB:
|
||||
*PTR(VADDR(sim, ins), uint8_t) = sim->reg[ins.rt];
|
||||
break;
|
||||
|
||||
case MIPS32R6_OP_SH:
|
||||
case MIPS_OP_SH:
|
||||
*PTR(VADDR(sim, ins), uint16_t) = sim->reg[ins.rt];
|
||||
break;
|
||||
|
||||
case MIPS32R6_OP_SW:
|
||||
case MIPS_OP_SW:
|
||||
*PTR(VADDR(sim, ins), uint32_t) = sim->reg[ins.rt];
|
||||
break;
|
||||
|
||||
case MIPS32R6_OP_SLTI:
|
||||
case MIPS_OP_SLTI:
|
||||
sim->reg[ins.rt] = (signed) sim->reg[ins.rs] <
|
||||
(signed) SE(ins.immd) ? 1 : 0;
|
||||
break;
|
||||
|
||||
case MIPS32R6_OP_SLTIU:
|
||||
case MIPS_OP_SLTIU:
|
||||
sim->reg[ins.rt] = sim->reg[ins.rs] < SE(ins.immd) ? 1 : 0;
|
||||
break;
|
||||
|
||||
case MIPS32R6_OP_ORI:
|
||||
case MIPS_OP_ORI:
|
||||
sim->reg[ins.rt] = sim->reg[ins.rs] | ins.immd;
|
||||
break;
|
||||
|
||||
case MIPS32R6_OP_XORI:
|
||||
case MIPS_OP_XORI:
|
||||
sim->reg[ins.rt] = sim->reg[ins.rs] ^ ins.immd;
|
||||
break;
|
||||
|
||||
|
|
156
msim/load.c
156
msim/load.c
|
@ -9,9 +9,6 @@
|
|||
#include "sim.h"
|
||||
|
||||
#define SEC_ALIGN 0x1000
|
||||
#define PAGE_SIZE 4096
|
||||
|
||||
#define BITFILED_LEN (UINT32_MAX / PAGE_SIZE / 8)
|
||||
|
||||
struct load_state {
|
||||
FILE *file;
|
||||
|
@ -109,112 +106,95 @@ static int load_phdr(struct load_state *state)
|
|||
return M_SUCCESS;
|
||||
}
|
||||
|
||||
static void set_page(uint8_t *bitfield, uint32_t addr)
|
||||
static int load_segment(struct simulator *sim,
|
||||
struct load_state *state, Elf32_Phdr *hdr)
|
||||
{
|
||||
int idx = (addr / PAGE_SIZE) / 8;
|
||||
int off = (addr / PAGE_SIZE) % 8;
|
||||
uint32_t off = B32(hdr->p_offset);
|
||||
uint32_t len = B32(hdr->p_filesz);
|
||||
uint32_t is_text = B32(hdr->p_flags) & PF_X;
|
||||
|
||||
bitfield[idx] |= 1 << off;
|
||||
}
|
||||
|
||||
static int get_page(const uint8_t *const bitfield, uint32_t addr)
|
||||
{
|
||||
int idx = (addr / PAGE_SIZE) / 8;
|
||||
int off = (addr / PAGE_SIZE) % 8;
|
||||
|
||||
return ((bitfield[idx] >> off) & 1);
|
||||
}
|
||||
|
||||
static int load_segment(struct simulator *sim, struct load_state *state,
|
||||
Elf32_Phdr *hdr, uint8_t* bitfield)
|
||||
{
|
||||
uint32_t addr = B32(hdr->p_vaddr),
|
||||
off = B32(hdr->p_offset),
|
||||
len = B32(hdr->p_filesz),
|
||||
flags = B32(hdr->p_flags);
|
||||
|
||||
bool exec = flags & PF_X;
|
||||
|
||||
// ignore if empty
|
||||
if (len < 1)
|
||||
return M_SUCCESS;
|
||||
|
||||
// make sure segment is acutally inside
|
||||
// the file
|
||||
if (BOUND_CHK(state->file_sz, len, off)) {
|
||||
ERROR("segment location invalid");
|
||||
return M_ERROR;
|
||||
}
|
||||
|
||||
// make sure the vitural address is also
|
||||
// valid
|
||||
if (BOUND_CHK(UINT32_MAX, len, addr)) {
|
||||
ERROR("segment vitural addr invalid");
|
||||
uintptr_t addr = 0;
|
||||
uint32_t add = 0;
|
||||
|
||||
if (len % SEC_ALIGN) {
|
||||
add = SEC_ALIGN - (len % SEC_ALIGN);
|
||||
len += add;
|
||||
}
|
||||
|
||||
if (is_text) {
|
||||
addr = sim->text_max;
|
||||
sim->text_max += len;
|
||||
} else {
|
||||
addr = sim->data_max;
|
||||
sim->data_max += len;
|
||||
}
|
||||
|
||||
bool read = B32(hdr->p_flags) & PF_R;
|
||||
bool write = B32(hdr->p_flags) & PF_W;
|
||||
|
||||
uint32_t prot = 0;
|
||||
if (read)
|
||||
prot |= PROT_READ;
|
||||
if (write)
|
||||
prot |= PROT_WRITE;
|
||||
|
||||
void *res = mmap((void*)addr, len, prot, MAP_PRIVATE | MAP_FIXED,
|
||||
state->fd, off);
|
||||
|
||||
if ((uintptr_t)res != addr) {
|
||||
PERROR("failed to map executable");
|
||||
return M_ERROR;
|
||||
}
|
||||
|
||||
// update text seg bounds
|
||||
if (exec) {
|
||||
if (addr < sim->text_min)
|
||||
sim->text_min = addr;
|
||||
if (addr + len > sim->text_max)
|
||||
sim->text_max = addr + len;
|
||||
}
|
||||
|
||||
// align the mapping ptr to
|
||||
// the page size
|
||||
uintptr_t ptr = (addr / PAGE_SIZE) * PAGE_SIZE;
|
||||
|
||||
// map each page that the segment
|
||||
// requires
|
||||
for (; ptr < addr + len; ptr += PAGE_SIZE) {
|
||||
// dont remap if address is
|
||||
// already mapped
|
||||
if (get_page(bitfield, ptr))
|
||||
continue;
|
||||
|
||||
// set page as mapped
|
||||
set_page(bitfield, ptr);
|
||||
|
||||
void *res = mmap(
|
||||
(void *) ptr, PAGE_SIZE,
|
||||
PROT_READ | PROT_WRITE,
|
||||
MAP_PRIVATE | MAP_FIXED | MAP_ANONYMOUS, -1, 0);
|
||||
|
||||
if ((uintptr_t) res != ptr) {
|
||||
PERROR("failed to map executable");
|
||||
return M_ERROR;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// load the segment into the mapped memory
|
||||
fseek(state->file, off, SEEK_SET);
|
||||
fread((void *) (uintptr_t) addr, 1, len, state->file);
|
||||
|
||||
return M_SUCCESS;
|
||||
}
|
||||
|
||||
static int load_memory(struct simulator *sim, struct load_state *state)
|
||||
{
|
||||
// map each page in a 32bit address space to a single bit
|
||||
// in the bitfield
|
||||
uint8_t *bitfield = malloc(BITFILED_LEN);
|
||||
if (bitfield == NULL) {
|
||||
PERROR("cannot alloc");
|
||||
return M_ERROR;
|
||||
}
|
||||
memset(bitfield, 0, BITFILED_LEN);
|
||||
uint32_t base = 0;
|
||||
|
||||
for (uint32_t i = 0; i < state->phdr_len; i++) {
|
||||
Elf32_Phdr *hdr = &state->phdr[i];
|
||||
Elf32_Phdr *hdr = NULL;
|
||||
uint32_t min = UINT32_MAX;
|
||||
|
||||
if (load_segment(sim, state, hdr, bitfield))
|
||||
if (B32(state->phdr[i].p_filesz) < 1)
|
||||
continue;
|
||||
|
||||
// we need to load segments in order
|
||||
for (uint32_t j = 0; j < state->phdr_len; j++) {
|
||||
Elf32_Phdr *temp = &state->phdr[j];
|
||||
uint32_t off = B32(temp->p_offset);
|
||||
uint32_t len = B32(temp->p_filesz);
|
||||
|
||||
if (len < 1)
|
||||
continue;
|
||||
|
||||
if (off <= base)
|
||||
continue;
|
||||
|
||||
if (off >= min)
|
||||
continue;
|
||||
|
||||
min = off;
|
||||
hdr = temp;
|
||||
}
|
||||
|
||||
base = min;
|
||||
|
||||
if (hdr == NULL) {
|
||||
ERROR("invalid elf phdr");
|
||||
return M_ERROR;
|
||||
}
|
||||
|
||||
if (load_segment(sim, state, hdr))
|
||||
return M_ERROR;
|
||||
}
|
||||
|
||||
free(bitfield);
|
||||
|
||||
return M_SUCCESS;
|
||||
}
|
||||
|
||||
|
|
|
@ -34,6 +34,7 @@ struct simulator_args {
|
|||
struct simulator {
|
||||
struct simulator_args *args;
|
||||
|
||||
|
||||
/// the registers
|
||||
uint32_t reg[32];
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ pc: 0x00400004
|
|||
ins: 0x0108409a
|
||||
registers:
|
||||
$zero: 0x00000000 $t0: 0x00000000 $s0: 0x00000000 $t8: 0x00000000
|
||||
$at: 0x10000000 $t1: 0x00000000 $s1: 0x00000000 $t9: 0x00000000
|
||||
$at: 0x00000000 $t1: 0x00000000 $s1: 0x00000000 $t9: 0x00000000
|
||||
$v0: 0x00000000 $t2: 0x00000000 $s2: 0x00000000 $k0: 0x00000000
|
||||
$v1: 0x00000000 $t3: 0x00000000 $s3: 0x00000000 $k1: 0x00000000
|
||||
$a0: 0x00000000 $t4: 0x00000000 $s4: 0x00000000 $gp: 0x00000000
|
||||
|
|
|
@ -6,7 +6,7 @@ pc: 0x00400000
|
|||
ins: 0x8c080000
|
||||
registers:
|
||||
$zero: 0x00000000 $t0: 0x00000000 $s0: 0x00000000 $t8: 0x00000000
|
||||
$at: 0x10000000 $t1: 0x00000000 $s1: 0x00000000 $t9: 0x00000000
|
||||
$at: 0x00000000 $t1: 0x00000000 $s1: 0x00000000 $t9: 0x00000000
|
||||
$v0: 0x00000000 $t2: 0x00000000 $s2: 0x00000000 $k0: 0x00000000
|
||||
$v1: 0x00000000 $t3: 0x00000000 $s3: 0x00000000 $k1: 0x00000000
|
||||
$a0: 0x00000000 $t4: 0x00000000 $s4: 0x00000000 $gp: 0x00000000
|
||||
|
|
Loading…
Reference in a new issue