1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
|
#include "mips.h"
struct mips_cpu_impl
{
uint32_t pc;
uint32_t pcNext;
uint32_t regs[32];
mips_mem_h mem;
unsigned logLevel;
FILE *logDst;
};
mips_error mips_cpu_get_register(
mips_cpu_h state, //!< Valid (non-empty) handle to a CPU
unsigned index, //!< Index from 0 to 31
uint32_t *value //!< Where to write the value to
)
{
// TODO : error handling
*value = state->regs[index];
return mips_Success;
}
/*! Modifies one of the 32 general purpose MIPS registers. */
mips_error mips_cpu_set_register(
mips_cpu_h state, //!< Valid (non-empty) handle to a CPU
unsigned index, //!< Index from 0 to 31
uint32_t value //!< New value to write into register file
)
{
// TODO : error handling
state->regs[index] = value;
return mips_Success;
}
mips_error mips_cpu_set_debug_level(mips_cpu_h state, unsigned level, FILE *dest)
{
state->logLevel = level;
state->logDst = dest;
return mips_Success;
}
mips_cpu_h mips_cpu_create(mips_mem_h mem)
{
mips_cpu_impl *cpu=new mips_cpu_impl;
cpu->pc=0;
for(int i=0;i<32;i++){
cpu->regs[i]=0;
}
cpu->mem=mem;
return cpu;
}
/*! \param pData Array of 4 bytes
\retval The big-endian equivlent
*/
uint32_t to_big(const uint8_t *pData)
{
return
(((uint32_t)pData[0])<<24)
|
(((uint32_t)pData[1])<<16)
|
(((uint32_t)pData[2])<<8)
|
(((uint32_t)pData[3])<<0);
}
mips_error mips_cpu_step(
mips_cpu_h state //! Valid (non-empty) handle to a CPU
)
{
uint8_t buffer[4];
mips_error err=mips_mem_read(
state->mem, //!< Handle to target memory
state->pc, //!< Byte address to start transaction at
4, //!< Number of bytes to transfer
buffer //!< Receives the target bytes
);
if(err!=0){
return err;
}
uint32_t instruction= to_big(buffer);
uint32_t opcode = (instruction>>26) & 0x3F;
uint32_t src1 = (instruction>> 21 ) & 0x1F;
uint32_t src2 = (instruction>> 16 ) & 0x1F;
uint32_t dst = (instruction>> 11 ) & 0x1F;
uint32_t shift = (instruction>> 6 ) & 0x1F ;
uint32_t function = (instruction>> 0 ) & 0x3F ;
if(opcode == 0){
// This is R-type
if(state->logLevel >= 2){
fprintf(state->logDst, "R-Type : dst=%u, src1=%u, src2=%u, shift=%u, function=%u.\n instr=%08x\n",
dst, src1, src2, shift, function, instruction
);
}
if(function == 0x21){
if(state->logLevel >= 1){
fprintf(state->logDst, "addu %u, %u, %u.\n", dst, src1, src2);
}
uint32_t va=state->regs[src1];
uint32_t vb=state->regs[src2];
uint32_t res=va+vb;
state->regs[dst] = res; // NOTE: what about zero reg?
// NOTE : What about updating the program counter
return mips_Success;
}else{
return mips_ErrorNotImplemented;
}
}else{
return mips_ErrorNotImplemented;
}
}
|