Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
Shen, Siran
arm11_
Commits
4c689fc3
Commit
4c689fc3
authored
Jun 06, 2020
by
sea19
Browse files
Better file structure sorted and makefile works
parent
6fc918d8
Changes
10
Hide whitespace changes
Inline
Side-by-side
src/Makefile
View file @
4c689fc3
CC
=
gcc
CFLAGS
=
-Wall
-g
-D_POSIX_SOURCE
-D_BSD_SOURCE
-std
=
c99
-Werror
-pedantic
CFLAGS
=
-Wall
-g
-std
=
c99
-Werror
-pedantic
FILES
=
emulate.c fetch.c decode.c execute.c instrType.c
.SUFFIXES
:
.c .o
#.PHONY: all clean
.PHONY
:
all clean
all
:
assemble emulate
assemble
:
assemble.o
emulate
:
emulate.o
all
:
emulate.o fetch.o execute.o decode.o instrType.o
$(CC)
$(CFLAGS)
$(FILES)
-o
emulate
clean
:
rm
-f
$(
wildcard
*
.o
)
...
...
src/decode.c
0 → 100644
View file @
4c689fc3
#include "decode.h"
void
decode
(
unsigned
int
instruction
,
decoded
*
decodedInstr
)
{
unsigned
int
bit26and27
=
(
instruction
>>
26
)
&
3
;
decodedInstr
->
condition
=
(
instruction
>>
28
)
&
0xf
;
decodedInstr
->
bit0to25
=
(
instruction
)
&
0x3ffffff
;
if
(
bit26and27
==
0
)
{
if
(((
instruction
>>
22
)
&
0xf
)
==
0
&&
((
instruction
>>
4
)
&
0xf
)
==
9
)
{
decodedInstr
->
type
=
multiply
;
}
else
{
findOpcode
(
decodedInstr
,
instruction
);
}
}
else
if
(
bit26and27
==
1
)
{
decodedInstr
->
type
=
singledata
;
}
else
if
(
bit26and27
==
2
)
{
decodedInstr
->
type
=
branch
;
}
}
void
findOpcode
(
decoded
*
decodedInstr
,
unsigned
int
instruction
)
{
unsigned
int
opcode
=
(
instruction
>>
21
)
&
0xf
;
if
(
opcode
==
0
)
{
decodedInstr
->
type
=
and
;
}
else
if
(
opcode
==
1
)
{
decodedInstr
->
type
=
eor
;
}
else
if
(
opcode
==
2
)
{
decodedInstr
->
type
=
sub
;
}
else
if
(
opcode
==
3
)
{
decodedInstr
->
type
=
rsb
;
}
else
if
(
opcode
==
4
)
{
decodedInstr
->
type
=
add
;
}
else
if
(
opcode
==
8
)
{
decodedInstr
->
type
=
tst
;
}
else
if
(
opcode
==
9
)
{
decodedInstr
->
type
=
teq
;
}
else
if
(
opcode
==
10
)
{
decodedInstr
->
type
=
cmp
;
}
else
if
(
opcode
==
12
)
{
decodedInstr
->
type
=
orr
;
}
else
if
(
opcode
==
13
)
{
decodedInstr
->
type
=
mov
;
}
}
src/decode.h
0 → 100644
View file @
4c689fc3
#ifndef DECODE_H
#define DECODE_H
typedef
enum
{
and
,
eor
,
sub
,
rsb
,
add
,
tst
,
teq
,
cmp
,
orr
,
mov
,
multiply
,
branch
,
singledata
}
type
;
typedef
struct
decoded
{
type
type
;
unsigned
int
condition
;
unsigned
int
bit0to25
;
}
decoded
;
void
findOpcode
(
decoded
*
decodedInstr
,
unsigned
int
instruction
);
//Finds the opcode of a data processing instruction
void
decode
(
unsigned
int
instruction
,
decoded
*
decodedInstr
);
//Decodes the instruction and stores it in decodedInstr
#endif
src/emulate.c
View file @
4c689fc3
...
...
@@ -2,588 +2,14 @@
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include "decode.h"
#include "fetch.h"
#include "execute.h"
#define NREGS 17
#define STACK_SIZE 16384 //Defined stack as ints which are 4 bytes so (64*1024)/4
#define PC 15
typedef
enum
{
and
,
eor
,
sub
,
rsb
,
add
,
tst
,
teq
,
cmp
,
orr
,
mov
,
multiply
,
branch
,
singledata
}
type
;
typedef
struct
decoded
{
type
type
;
unsigned
int
condition
;
unsigned
int
bit0to25
;
}
decoded
;
typedef
struct
decoded_data_processing
{
type
type
;
unsigned
int
rn
,
rd
,
operand2
,
s_bit
;
unsigned
int
carry_out
,
val_reg_last12bits
;
}
decoded_dp
;
typedef
struct
arm_state
{
unsigned
int
regs
[
NREGS
];
unsigned
int
*
memory
;
// *objectcode
int
n
,
z
,
c
,
v
;
}
armstate
;
void
armstate_init
(
armstate
*
state
)
{
/* zero out all arm state */
state
->
n
=
0
;
state
->
z
=
0
;
state
->
c
=
0
;
state
->
v
=
0
;
for
(
int
i
=
0
;
i
<
NREGS
;
i
++
)
{
state
->
regs
[
i
]
=
0
;
}
state
->
memory
=
calloc
(
STACK_SIZE
,
sizeof
(
int
));
}
char
*
printenum
(
type
t
)
{
//Testing
switch
(
t
)
{
case
and
:
return
"and"
;
break
;
case
eor
:
return
"eor"
;
break
;
case
sub
:
return
"sub"
;
break
;
case
rsb
:
return
"rsb"
;
break
;
case
add
:
return
"add"
;
break
;
case
tst
:
return
"tst"
;
break
;
case
teq
:
return
"cmp"
;
break
;
case
cmp
:
return
"cmp"
;
break
;
case
orr
:
return
"orr"
;
break
;
case
mov
:
return
"mov"
;
break
;
case
multiply
:
return
"mul"
;
break
;
case
branch
:
return
"branch"
;
break
;
case
singledata
:
return
"singledata"
;
break
;
}
return
"NULL"
;
}
void
findOpcode
(
decoded
*
decodedInstr
,
unsigned
int
instruction
)
{
unsigned
int
opcode
=
(
instruction
>>
21
)
&
0xf
;
if
(
opcode
==
0
)
{
decodedInstr
->
type
=
and
;
}
else
if
(
opcode
==
1
)
{
decodedInstr
->
type
=
eor
;
}
else
if
(
opcode
==
2
)
{
decodedInstr
->
type
=
sub
;
}
else
if
(
opcode
==
3
)
{
decodedInstr
->
type
=
rsb
;
}
else
if
(
opcode
==
4
)
{
decodedInstr
->
type
=
add
;
}
else
if
(
opcode
==
8
)
{
decodedInstr
->
type
=
tst
;
}
else
if
(
opcode
==
9
)
{
decodedInstr
->
type
=
teq
;
}
else
if
(
opcode
==
10
)
{
decodedInstr
->
type
=
cmp
;
}
else
if
(
opcode
==
12
)
{
decodedInstr
->
type
=
orr
;
}
else
if
(
opcode
==
13
)
{
decodedInstr
->
type
=
mov
;
}
}
// next_instruction_condition_check
int
do_next_instruction
(
decoded
*
decodedInstr
,
armstate
*
state
){
unsigned
int
cond
=
decodedInstr
->
condition
;
int
run_command
;
if
((
cond
==
0
)
&&
(
state
->
z
==
1
))
{
// cond in decimal?
run_command
=
1
;
}
else
if
((
cond
==
1
)
&&
(
state
->
z
==
0
))
{
run_command
=
1
;
}
else
if
((
cond
==
10
)
&&
(
state
->
n
==
state
->
v
))
{
run_command
=
1
;
}
else
if
((
cond
==
11
)
&&
(
state
->
n
!=
state
->
v
))
{
run_command
=
1
;
}
else
if
(
cond
==
12
&&
state
->
z
==
0
&&
state
->
n
==
state
->
v
)
{
run_command
=
1
;
}
else
if
(
cond
==
13
&&
(
state
->
z
==
1
||
state
->
n
!=
state
->
v
))
{
run_command
=
1
;
}
else
if
(
cond
==
14
){
run_command
=
1
;
}
else
{
run_command
=
0
;
}
return
run_command
;
}
//Operand2 is a register
void
val_reg_last12bits
(
decoded
*
decodedInstr
,
unsigned
int
*
operand2
,
armstate
*
state
)
{
unsigned
int
iw
=
decodedInstr
->
bit0to25
;
unsigned
int
val_in_rm
=
state
->
regs
[
iw
&
0xF
];
// state -> regs[iw & 0xF] == Rm
unsigned
int
sh_op
=
(
iw
>>
4
)
&
0
b1
;
unsigned
int
sh_type
=
(
iw
>>
5
)
&
0
b11
;
unsigned
int
amount
;
if
(
sh_op
==
0
){
amount
=
(
iw
>>
7
)
&
0
b11111
;
}
else
{
amount
=
state
->
regs
[
iw
>>
8
&
0xF
];
}
//how_to_shift(sh_type, amount, val_in_rm)
switch
(
sh_type
)
{
case
0
:
*
operand2
=
val_in_rm
<<
amount
;
break
;
case
1
:
*
operand2
=
val_in_rm
>>
amount
;
break
;
case
2
:
*
operand2
=
(
signed
)
val_in_rm
>>
amount
;
break
;
case
3
:
*
operand2
=
val_in_rm
>>
amount
||
((
val_in_rm
&
amount
)
<<
(
32
-
amount
));
// ??????????
break
;
default
:
exit
(
1
);
}
}
// the carry out of shift op
unsigned
int
shift_carry_out
(
decoded_dp
*
decodedDp
,
decoded
*
decodedInstr
,
armstate
*
state
){
unsigned
int
immediate
,
carry_out
,
val
,
amount
;
unsigned
int
sh_type
,
sh_op
;
unsigned
int
iw
=
decodedInstr
->
bit0to25
;
immediate
=
(
iw
>>
25
)
&
0
b1
;
if
(
immediate
==
1
){
amount
=
(
iw
>>
8
)
&
0xF
;
val
=
(
iw
&
0xFF
);
carry_out
=
val
>>
amount
&
0
b1
;
}
else
{
val
=
state
->
regs
[
iw
&
0xF
];
sh_type
=
(
iw
>>
5
)
&
0
b11
;
sh_op
=
(
iw
>>
4
)
&
0
b1
;
if
(
sh_op
==
0
){
amount
=
(
iw
>>
7
)
&
0
b11111
;
}
else
{
amount
=
state
->
regs
[
iw
>>
8
&
0xF
];
}
if
(
sh_type
==
0
){
carry_out
=
decodedDp
->
val_reg_last12bits
>>
(
32
-
amount
)
&
0
b1
;
}
else
{
carry_out
=
decodedDp
->
val_reg_last12bits
>>
amount
&
0
b1
;
}
}
decodedDp
->
carry_out
=
carry_out
;
return
decodedDp
->
carry_out
;
}
void
decode_data_processing
(
decoded
*
decodedInstr
,
decoded_dp
*
decodedDp
,
armstate
*
state
){
unsigned
int
immediate
,
iw
,
operand2
;
iw
=
decodedInstr
->
bit0to25
;
decodedDp
->
type
=
decodedInstr
->
type
;
decodedDp
->
rd
=
(
iw
>>
12
)
&
0xF
;
decodedDp
->
rn
=
(
iw
>>
16
)
&
0xF
;
decodedDp
->
s_bit
=
(
iw
>>
20
)
&
0
b1
;
immediate
=
(
iw
>>
25
)
&
0
b1
;
if
(
immediate
==
1
){
operand2
=
iw
&
0xfff
;
}
else
{
val_reg_last12bits
(
decodedInstr
,
&
operand2
,
state
);
}
decodedDp
->
operand2
=
operand2
;
printf
(
"operand2: %d
\n
"
,
operand2
);
}
void
and_instr
(
decoded
*
decodedInstr
,
armstate
*
state
){
decoded_dp
*
decodedDp
=
calloc
(
1
,
sizeof
(
decoded_dp
));
decode_data_processing
(
decodedInstr
,
decodedDp
,
state
);
unsigned
int
res
=
(
state
->
regs
[
decodedDp
->
rn
]
&
decodedDp
->
operand2
);
state
->
regs
[
decodedDp
->
rd
]
=
res
;
if
(
decodedDp
->
s_bit
==
1
){
state
->
c
=
shift_carry_out
(
decodedDp
,
decodedInstr
,
state
);
state
->
n
=
(
res
>>
31
)
&
0
b1
;
if
(
res
==
0
){
state
->
z
=
1
;
}
else
{
state
->
z
=
0
;
}
}
free
(
decodedDp
);
}
void
eor_instr
(
decoded
*
decodedInstr
,
armstate
*
state
){
decoded_dp
*
decodedDp
=
calloc
(
1
,
sizeof
(
decoded_dp
));
decode_data_processing
(
decodedInstr
,
decodedDp
,
state
);
unsigned
int
res
=
(
state
->
regs
[
decodedDp
->
rn
]
^
decodedDp
->
operand2
);
state
->
regs
[
decodedDp
->
rd
]
=
res
;
if
(
decodedDp
->
s_bit
==
1
){
state
->
c
=
shift_carry_out
(
decodedDp
,
decodedInstr
,
state
);
state
->
n
=
(
res
>>
31
)
&
0
b1
;
if
(
res
==
0
){
state
->
z
=
1
;
}
else
{
state
->
z
=
0
;
}
}
free
(
decodedDp
);
}
void
sub_instr
(
decoded
*
decodedInstr
,
armstate
*
state
){
decoded_dp
*
decodedDp
=
calloc
(
1
,
sizeof
(
decoded_dp
));
decode_data_processing
(
decodedInstr
,
decodedDp
,
state
);
unsigned
int
res
=
(
state
->
regs
[
decodedDp
->
rn
]
-
decodedDp
->
operand2
);
state
->
regs
[
decodedDp
->
rd
]
=
res
;
if
(
decodedDp
->
s_bit
==
1
){
if
(
state
->
regs
[
decodedDp
->
rn
]
<
decodedDp
->
operand2
){
state
->
c
=
0
;
}
else
{
state
->
c
=
1
;
}
state
->
n
=
(
res
>>
31
)
&
0
b1
;
if
(
res
==
0
){
state
->
z
=
1
;
}
else
{
state
->
z
=
0
;
}
}
free
(
decodedDp
);
}
void
rsb_instr
(
decoded
*
decodedInstr
,
armstate
*
state
){
decoded_dp
*
decodedDp
=
calloc
(
1
,
sizeof
(
decoded_dp
));
decode_data_processing
(
decodedInstr
,
decodedDp
,
state
);
unsigned
int
res
=
decodedDp
->
operand2
-
state
->
regs
[
decodedDp
->
rn
];
state
->
regs
[
decodedDp
->
rd
]
=
res
;
if
(
decodedDp
->
s_bit
==
1
){
if
(
decodedDp
->
operand2
<
state
->
regs
[
decodedDp
->
rn
]){
state
->
c
=
0
;
}
else
{
state
->
c
=
1
;
}
state
->
n
=
(
res
>>
31
)
&
0
b1
;
if
(
res
==
0
){
state
->
z
=
1
;
}
else
{
state
->
z
=
0
;
}
}
free
(
decodedDp
);
}
void
add_instr
(
decoded
*
decodedInstr
,
armstate
*
state
){
decoded_dp
*
decodedDp
=
calloc
(
1
,
sizeof
(
decoded_dp
));
decode_data_processing
(
decodedInstr
,
decodedDp
,
state
);
unsigned
int
res
=
decodedDp
->
operand2
+
state
->
regs
[
decodedDp
->
rn
];
state
->
regs
[
decodedDp
->
rd
]
=
res
;
if
(
decodedDp
->
s_bit
==
1
){
if
(
res
<=
0xFFFFFFFF
){
state
->
c
=
0
;
}
else
{
state
->
c
=
1
;
}
state
->
n
=
(
res
>>
31
)
&
0
b1
;
if
(
res
==
0
){
state
->
z
=
1
;
}
else
{
state
->
z
=
0
;
}
}
free
(
decodedDp
);
}
void
tst_instr
(
decoded
*
decodedInstr
,
armstate
*
state
){
decoded_dp
*
decodedDp
=
calloc
(
1
,
sizeof
(
decoded_dp
));
decode_data_processing
(
decodedInstr
,
decodedDp
,
state
);
unsigned
int
res
=
decodedDp
->
operand2
+
state
->
regs
[
decodedDp
->
rn
];
if
(
decodedDp
->
s_bit
==
1
){
if
(
res
<=
0xFFFFFFFF
){
state
->
c
=
0
;
}
else
{
state
->
c
=
1
;
}
state
->
n
=
(
res
>>
31
)
&
0
b1
;
if
(
res
==
0
){
state
->
z
=
1
;
}
else
{
state
->
z
=
0
;
}
}
free
(
decodedDp
);
}
void
teq_instr
(
decoded
*
decodedInstr
,
armstate
*
state
){
decoded_dp
*
decodedDp
=
calloc
(
1
,
sizeof
(
decoded_dp
));
decode_data_processing
(
decodedInstr
,
decodedDp
,
state
);
unsigned
res
=
(
state
->
regs
[
decodedDp
->
rn
]
^
decodedDp
->
operand2
);
if
(
decodedDp
->
s_bit
==
1
){
state
->
c
=
shift_carry_out
(
decodedDp
,
decodedInstr
,
state
);
state
->
n
=
(
res
>>
31
)
&
0
b1
;
if
(
res
==
0
){
state
->
z
=
1
;
}
else
{
state
->
z
=
0
;
}
}
free
(
decodedDp
);
}
void
cmp_instr
(
decoded
*
decodedInstr
,
armstate
*
state
){
decoded_dp
*
decodedDp
=
calloc
(
1
,
sizeof
(
decoded_dp
));
decode_data_processing
(
decodedInstr
,
decodedDp
,
state
);
unsigned
res
=
(
state
->
regs
[
decodedDp
->
rn
]
-
decodedDp
->
operand2
);
if
(
decodedDp
->
s_bit
==
1
){
if
(
state
->
regs
[
decodedDp
->
rn
]
<
decodedDp
->
operand2
){
state
->
c
=
0
;
}
else
{
state
->
c
=
1
;
}
state
->
n
=
(
res
>>
31
)
&
0
b1
;
if
(
res
==
0
){
state
->
z
=
1
;
}
else
{
state
->
z
=
0
;
}
}
free
(
decodedDp
);
}
void
orr_instr
(
decoded
*
decodedInstr
,
armstate
*
state
){
decoded_dp
*
decodedDp
=
calloc
(
1
,
sizeof
(
decoded_dp
));
decode_data_processing
(
decodedInstr
,
decodedDp
,
state
);
unsigned
int
res
=
(
state
->
regs
[
decodedDp
->
rn
]
||
decodedDp
->
operand2
);
state
->
regs
[
decodedDp
->
rd
]
=
res
;
if
(
decodedDp
->
s_bit
==
1
){
state
->
c
=
shift_carry_out
(
decodedDp
,
decodedInstr
,
state
);
state
->
n
=
(
res
>>
31
)
&
0
b1
;
if
(
res
==
0
){
state
->
z
=
1
;
}
else
{
state
->
z
=
0
;
}
}
free
(
decodedDp
);
}
void
mov_instr
(
decoded
*
decodedInstr
,
armstate
*
state
){
decoded_dp
*
decodedDp
=
calloc
(
1
,
sizeof
(
decoded_dp
));
decode_data_processing
(
decodedInstr
,
decodedDp
,
state
);
state
->
regs
[
decodedDp
->
rd
]
=
decodedDp
->
operand2
;
if
(
decodedDp
->
s_bit
==
1
){
state
->
c
=
shift_carry_out
(
decodedDp
,
decodedInstr
,
state
);
state
->
n
=
(
decodedDp
->
operand2
>>
31
)
&
0
b1
;
if
(
decodedDp
->
operand2
==
0
){
state
->
z
=
1
;
}
else
{
state
->
z
=
0
;
}
}
free
(
decodedDp
);
}
void
single_data_transfer_instr
(
decoded
*
decodedInstr
,
armstate
*
state
){
unsigned
int
iw
,
immediate
,
offset
,
p_index
,
up_bit
,
load_bit
,
rn
,
rd
;
unsigned
int
data
;
iw
=
decodedInstr
->
bit0to25
;
immediate
=
(
iw
>>
25
)
&
0
b1
;
//0 - 24 bits 没了(第二十五位
p_index
=
(
iw
>>
24
)
&
0
b1
;
up_bit
=
(
iw
>>
23
)
&
0
b1
;
load_bit
=
(
iw
>>
20
)
&
0
b1
;
rn
=
(
iw
>>
16
)
&
0xF
;
rd
=
(
iw
>>
12
)
&
0xF
;
//calculate the offset
if
(
immediate
==
0
)
{
offset
=
iw
&
0xFFF
;
}
else
{
// Operand2 is a register, return the value of offset / op2
val_reg_last12bits
(
decodedInstr
,
&
offset
,
state
);
}
if
(
p_index
==
1
){
if
(
up_bit
==
1
){
data
=
offset
+
state
->
regs
[
rn
];
}
else
{
data
=
state
->
regs
[
rn
]
-
offset
;
}
}
else
{
if
(
up_bit
==
1
){
data
=
state
->
regs
[
rn
];
state
->
regs
[
rn
]
+=
offset
;
}
else
{
data
=
state
->
regs
[
rn
];
state
->
regs
[
rn
]
-=
offset
;
}
}
if
(
load_bit
==
1
)
{
char
*
byteMem
=
(
char
*
)
state
->
memory
;
int
*
memAdd
=
(
int
*
)(
byteMem
+
data
);
state
->
regs
[
rd
]
=
*
memAdd
;
}
else
{
/*char *byteMem = state->memory;
int *memAdd = byteMem + data;
*memAdd = state->regs[rd];*/
}
}
void
multiply_instr
(
decoded
*
decodedInstr
,
armstate
*
state
){
unsigned
iw
,
acc
,
set
,
rd
,
rn
,
rs
,
rm
,
res
;
iw
=
decodedInstr
->
bit0to25
;;
acc
=
(
iw
>>
21
)
&
0
b1
;
set
=
(
iw
>>
20
)
&
0
b1
;
rd
=
(
iw
>>
16
)
&
0xf
;
rn
=
(
iw
>>
12
)
&
0xf
;
rs
=
(
iw
>>
8
)
&
0xf
;
rm
=
iw
&
0xf
;
if
(
acc
==
1
){
state
->
regs
[
rd
]
=
state
->
regs
[
rm
]
*
state
->
regs
[
rs
]
+
state
->
regs
[
rn
];
}
else
{
state
->
regs
[
rd
]
=
state
->
regs
[
rm
]
*
state
->
regs
[
rs
];
}
res
=
state
->
regs
[
rd
];
if
(
set
==
1
){
state
->
n
=
(
res
>>
31
)
&
0
b1
;
if
(
res
==
0
){
state
->
z
=
1
;
}
else
{
state
->
z
=
0
;
}
}
}
//not sure about branch execution///////////////
void
branch_instr
(
decoded
*
decodedInstr
,
armstate
*
state
){
signed
int
offset
;
unsigned
int
iw
=
decodedInstr
->
bit0to25
;
// shifted left 2 bits, sign extended to 32 bits??????????????
offset
=
(
iw
&
0x00ffffff
)
<<
2
;
int
sign
=
(
iw
>>
23
)
&
0
b1
;
if
(
sign
==
1
)
{
offset
=
offset
|
0xff000000
;
}
state
->
regs
[
PC
]
+=
offset
;
}
unsigned
int
fetch
(
unsigned
int
*
objectcode
,
unsigned
int
programCounter
)
{
return
objectcode
[
programCounter
];
//Returns an instruction at the value of programCounter
}
void
decode
(
unsigned
int
instruction
,
decoded
*
decodedInstr
)
{
unsigned
int
bit26and27
=
(
instruction
>>
26
)
&
0
b11
;
decodedInstr
->
condition
=
(
instruction
>>
28
)
&
0xf
;
decodedInstr
->
bit0to25
=
(
instruction
)
&
0x3ffffff
;