Commit 0920f5e4 authored by Frédéric Pétrot's avatar Frédéric Pétrot
Browse files

Updating the microblaze module

parent 95884ed9
This diff is collapsed.
......@@ -32,7 +32,7 @@
* been added in 9.2 (a MMU has been added, new mults and so on).
* Modifications will be added if we encounter gcc generated code that
* uses them.
\*/
\*/
#ifndef _SOCLIB_MICROBLAZE_ISS_H_
#define _SOCLIB_MICROBLAZE_ISS_H_
......@@ -43,9 +43,67 @@
#define R_IR_NOP 0x80000000
/*\
* Machine State Register bits
\*/
#define MSR_BE 0x1
#define MSR_IE 0x2
/*
* Microblaze doc says bit 0 (leftmost 'cause be) called cc is
* carry copy, i.e. always identical to bit 29.
*/
#define MSR_C 0x80000004
#define MSR_BIP 0x8
#define MSR_DZ 0x40
#define MSR_EIP 0x200
#define MSR_EE 0x100
/*\
* 32 bit extension of a 16 bit or a 8 bit number
\*/
#define SEXT16(imm) (((imm)&0x8000)?0xFFFF0000|(imm):(imm))
#define SEXT8(imm) (((imm)&0x80)?0xFFFFFF00|(imm):(imm))
/*\
* Conditional computation of the immediate value: a pure rhs
\*/
#define IMM_OP ((uint32_t)(m_imm ? (r_imm | ins_imm) : SEXT16(ins_imm)))
/*\
* Memory accesses to fit the current SoCLib Iss strategy
* The type, addr, dest and wdata fields are inherited from Iss
\*/
#define LOAD(type, addr) \
do { \
r_mem_req = true; \
r_mem_type = type; \
r_mem_addr = addr; \
r_mem_dest = ins_rd; \
} while (0)
#define STORE(type, addr, data) \
do { \
r_mem_req = true; \
r_mem_type = type; \
r_mem_addr = addr; \
r_mem_wdata = data; \
} while (0)
#define HANDLE_EXCEPTION \
do { \
r_gpr[17].u = r_pc; \
r_pc = EXCEPTION_VECTOR; \
r_npc = EXCEPTION_VECTOR + 4; \
r_msr |= MSR_EIP; \
return; \
} while (0)
/*\
* MicroBlaze Processor structure definition
\*/
\*/
namespace soclib {
namespace common {
class MicroBlazeIss
......@@ -76,7 +134,7 @@ namespace common {
/*\
* Possible instruction types and helper struct
\*/
\*/
enum {TYPEA, TYPEB, TYPEN};
typedef struct {
......@@ -86,34 +144,66 @@ namespace common {
/*\
* Instruction decoding tables
\*/
\*/
static const IFormat OpcodeTable[];
/*\
* Instruction decoding function
\*/
\*/
static inline void IDecode(uint32_t ins, char *opcode, int *rd, int *ra, int *rb, int *imm)
{
const IFormat *Code;
// Instruction decoding
Code = &OpcodeTable[(ins >> 26) & 0x3F];
*opcode = Code->opcode;
*ra = (ins >> 16) & 0x1F;
*rd = (ins >> 21) & 0x1F;
if (Code->format == TYPEA) {
*imm = ins & 0x07FF;
*rb = (ins >> 11) & 0x1F;
} else if (Code->format == TYPEB) {
*imm = ins & 0xFFFF;
} else { // Reserved instruction
fprintf(stderr, "Reserved instruction 0x%08x\n", ins);
}
};
// MicroBlaze Registers, all considered unsigned by default
{
const IFormat *Code;
// Instruction decoding
Code = &OpcodeTable[(ins >> 26) & 0x3F];
*opcode = Code->opcode;
*ra = (ins >> 16) & 0x1F;
*rd = (ins >> 21) & 0x1F;
if (Code->format == TYPEA) {
*imm = ins & 0x07FF;
*rb = (ins >> 11) & 0x1F;
} else if (Code->format == TYPEB) {
*imm = ins & 0xFFFF;
} else { // Reserved instruction
fprintf(stderr, "Reserved instruction 0x%08x\n", ins);
}
};
/*\
* Carry/borrow computations below thanks to Kane, as reminded in Hacker's delight 2-13, page 31
* compute_carry computes the carry (surprise!) so that the insns code is
* easier to read and factorized.
* set_carry sets the correct bit in the status register
* get_carry gives the carry
* I can safely rely on the compiler to do constant propagation and all the like when using -O3,
* so that the code is similar for all add and rsub operations.
\*/
static inline uint32_t compute_carry(uint32_t z, uint32_t a, uint32_t cin)
{
return cin ? z <= a : z < a;
}
inline void set_carry(uint32_t carry)
{
r_msr = carry ? r_msr | MSR_C : r_msr & ~MSR_C;
}
inline uint32_t get_carry(void)
{
/* Let's use the cc bit to spare a mask insn */
return r_msr >> 31;
}
// MicroBlaze Registers.
// They can (now) handle integer and floats through an anonymous union as modern
// (post 1994, I'd guess) C does not allow cast on lvalues anymore, what a shame!
// When integer, they are considered unsigned by default
// (quite important for the comparisons and shifts implementation)
uint32_t r_gpr[32]; // General Purpose Registers
union {
uint32_t u;
float f;
} r_gpr[32]; // General Purpose Registers
uint32_t r_imm; // Temporate Register
uint32_t r_msr; // Machine Status Register
uint32_t r_ear; // Exception address Register
......@@ -130,8 +220,8 @@ namespace common {
uint32_t m_rx; // Register in use when an unaligned access occurs
uint32_t r_pc; // Program Counter
uint32_t r_npc ; // Next Program Counter
bool r_mem_req;
uint32_t r_npc; // Next Program Counter
bool r_mem_req;
enum DataAccessType r_mem_type; // Data Cache access type
uint32_t r_mem_addr; // Data Cache address
uint32_t r_mem_wdata; // Data Cache data value (write)
......@@ -169,84 +259,86 @@ namespace common {
* Useless single stepping
\*/
inline void nullStep( uint32_t cycles = 1 )
{
}
{
}
inline uint32_t isBusy() {return 0;}
inline uint32_t isBusy()
{
return 0;
}
inline void getInstructionRequest(bool &req, uint32_t &address) const
{
req = true;
address = r_pc;
}
{
req = true;
address = r_pc;
}
inline void getDataRequest(
bool &valid,
enum DataAccessType &type,
uint32_t &address,
uint32_t &wdata) const
{
valid = r_mem_req;
address = r_mem_addr;
wdata = r_mem_wdata;
type = r_mem_type;
}
{
valid = r_mem_req;
address = r_mem_addr;
wdata = r_mem_wdata;
type = r_mem_type;
}
inline void setWriteBerr()
{
r_dbe = true;
}
{
r_dbe = true;
}
inline void setIrq(uint32_t irq)
{
m_irq = irq;
}
{
m_irq = irq;
}
/*\
* Feeds the Iss with an instruction to execute and an error
* status
\*/
inline void setInstruction(bool error, uint32_t insn)
{
m_ibe = error;
m_ir = soclib::endian::uint32_swap(insn);
};
{
m_ibe = error;
m_ir = soclib::endian::uint32_swap(insn);
};
/*\
* API for memory access through the Iss
\*/
void setDataResponse(bool error, uint32_t rdata);
int cpuCauseToSignal( uint32_t cause ) const;
// processor internal registers access API, used by
// debugger.
inline unsigned int getDebugRegisterCount() const
{
return 36;
}
{
return 36;
}
uint32_t getDebugRegisterValue(unsigned int reg) const;
inline size_t getDebugRegisterSize(unsigned int reg) const
{
return 32;
}
{
return 32;
}
void setDebugRegisterValue(unsigned int reg, uint32_t value);
inline uint32_t getDebugPC() const
{
return r_pc;
}
{
return r_pc;
}
inline void setDebugPC(uint32_t pc)
{
r_pc = pc;
r_npc = pc+4;
}
{
r_pc = pc;
r_npc = pc+4;
}
};
}
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment