1 |
d93979b7
|
Arnaud Dieumegard
|
|
2 |
|
|
-- Copyright (C) 1996 Morgan Kaufmann Publishers, Inc
|
3 |
|
|
|
4 |
|
|
-- This file is part of VESTs (Vhdl tESTs).
|
5 |
|
|
|
6 |
|
|
-- VESTs is free software; you can redistribute it and/or modify it
|
7 |
|
|
-- under the terms of the GNU General Public License as published by the
|
8 |
|
|
-- Free Software Foundation; either version 2 of the License, or (at
|
9 |
|
|
-- your option) any later version.
|
10 |
|
|
|
11 |
|
|
-- VESTs is distributed in the hope that it will be useful, but WITHOUT
|
12 |
|
|
-- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
13 |
|
|
-- FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
14 |
|
|
-- for more details.
|
15 |
|
|
|
16 |
|
|
-- You should have received a copy of the GNU General Public License
|
17 |
|
|
-- along with VESTs; if not, write to the Free Software Foundation,
|
18 |
|
|
-- Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
19 |
|
|
|
20 |
|
|
-- ---------------------------------------------------------------------
|
21 |
|
|
--
|
22 |
|
|
-- $Id: ch_15_dlxi-b.vhd,v 1.3 2001-10-26 16:29:35 paw Exp $
|
23 |
|
|
-- $Revision: 1.3 $
|
24 |
|
|
--
|
25 |
|
|
-- ---------------------------------------------------------------------
|
26 |
|
|
|
27 |
|
|
library bv_utilities;
|
28 |
|
|
|
29 |
|
|
package body dlx_instr is
|
30 |
|
|
|
31 |
|
|
use bv_utilities.bv_arithmetic.all;
|
32 |
|
|
|
33 |
|
|
constant opcode_names : opcode_name_array
|
34 |
|
|
:= ( "SPECIAL ", "FPARITH ", "J ", "JAL ",
|
35 |
|
|
"BEQZ ", "BNEZ ", "BFPT ", "BFPF ",
|
36 |
|
|
"ADDI ", "ADDUI ", "SUBI ", "SUBUI ",
|
37 |
|
|
"ANDI ", "ORI ", "XORI ", "LHI ",
|
38 |
|
|
"RFE ", "TRAP ", "JR ", "JALR ",
|
39 |
|
|
"SLLI ", "UNDEF_15", "SRLI ", "SRAI ",
|
40 |
|
|
"SEQI ", "SNEI ", "SLTI ", "SGTI ",
|
41 |
|
|
"SLEI ", "SGEI ", "UNDEF_1E", "UNDEF_1F",
|
42 |
|
|
"LB ", "LH ", "UNDEF_22", "LW ",
|
43 |
|
|
"LBU ", "LHU ", "LF ", "LD ",
|
44 |
|
|
"SB ", "SH ", "UNDEF_2A", "SW ",
|
45 |
|
|
"UNDEF_2C", "UNDEF_2D", "SF ", "SD ",
|
46 |
|
|
"SEQUI ", "SNEUI ", "SLTUI ", "SGTUI ",
|
47 |
|
|
"SLEUI ", "SGEUI ", "UNDEF_36", "UNDEF_37",
|
48 |
|
|
"UNDEF_38", "UNDEF_39", "UNDEF_3A", "UNDEF_3B",
|
49 |
|
|
"UNDEF_3C", "UNDEF_3D", "UNDEF_3E", "UNDEF_3F" );
|
50 |
|
|
|
51 |
|
|
constant sp_func_names : sp_func_name_array
|
52 |
|
|
:= ( "NOP ", "UNDEF_01", "UNDEF_02", "UNDEF_03",
|
53 |
|
|
"SLL ", "UNDEF_05", "SRL ", "SRA ",
|
54 |
|
|
"UNDEF_08", "UNDEF_09", "UNDEF_0A", "UNDEF_0B",
|
55 |
|
|
"UNDEF_0C", "UNDEF_0D", "UNDEF_0E", "UNDEF_0F",
|
56 |
|
|
"SEQU ", "SNEU ", "SLTU ", "SGTU ",
|
57 |
|
|
"SLEU ", "SGEU ", "UNDEF_16", "UNDEF_17",
|
58 |
|
|
"UNDEF_18", "UNDEF_19", "UNDEF_1A", "UNDEF_1B",
|
59 |
|
|
"UNDEF_1C", "UNDEF_1D", "UNDEF_1E", "UNDEF_1F",
|
60 |
|
|
"ADD ", "ADDU ", "SUB ", "SUBU ",
|
61 |
|
|
"AND ", "OR ", "XOR ", "UNDEF_27",
|
62 |
|
|
"SEQ ", "SNE ", "SLT ", "SGT ",
|
63 |
|
|
"SLE ", "SGE ", "UNDEF_2E", "UNDEF_2F",
|
64 |
|
|
"MOVI2S ", "MOVS2I ", "MOVF ", "MOVD ",
|
65 |
|
|
"MOVFP2I ", "MOVI2FP ", "UNDEF_36", "UNDEF_37",
|
66 |
|
|
"UNDEF_38", "UNDEF_39", "UNDEF_3A", "UNDEF_3B",
|
67 |
|
|
"UNDEF_3C", "UNDEF_3D", "UNDEF_3E", "UNDEF_3F" );
|
68 |
|
|
|
69 |
|
|
constant fp_func_names : fp_func_name_array
|
70 |
|
|
:= ( "ADDF ", "SUBF ", "MULTF ", "DIVF ",
|
71 |
|
|
"ADDD ", "SUBD ", "MULTD ", "DIVD ",
|
72 |
|
|
"CVTF2D ", "CVTF2I ", "CVTD2F ", "CVTD2I ",
|
73 |
|
|
"CVTI2F ", "CVTI2D ", "MULT ", "DIV ",
|
74 |
|
|
"EQF ", "NEF ", "LTF ", "GTF ",
|
75 |
|
|
"LEF ", "GEF ", "MULTU ", "DIVU ",
|
76 |
|
|
"EQD ", "NED ", "LTD ", "GTD ",
|
77 |
|
|
"LED ", "GED ", "UNDEF_1E", "UNDEF_1F" );
|
78 |
|
|
|
79 |
|
|
|
80 |
|
|
procedure disassemble ( instr : dlx_bv_word;
|
81 |
|
|
disassembled_instr : out string; len : out positive ) is
|
82 |
|
|
|
83 |
|
|
alias norm_disassembled_instr : string(1 to disassembled_instr'length)
|
84 |
|
|
is disassembled_instr;
|
85 |
|
|
|
86 |
|
|
alias instr_opcode : dlx_opcode is instr(0 to 5);
|
87 |
|
|
alias instr_sp_func : dlx_sp_func is instr(26 to 31);
|
88 |
|
|
alias instr_fp_func : dlx_fp_func is instr(27 to 31);
|
89 |
|
|
alias instr_rs1 : dlx_reg_addr is instr(6 to 10);
|
90 |
|
|
alias instr_rs2 : dlx_reg_addr is instr(11 to 15);
|
91 |
|
|
alias instr_Itype_rd : dlx_reg_addr is instr(11 to 15);
|
92 |
|
|
alias instr_Rtype_rd : dlx_reg_addr is instr(16 to 20);
|
93 |
|
|
alias instr_immed16 : dlx_immed16 is instr(16 to 31);
|
94 |
|
|
alias instr_immed26 : dlx_immed26 is instr(6 to 31);
|
95 |
|
|
|
96 |
|
|
variable instr_opcode_num : dlx_opcode_num;
|
97 |
|
|
variable instr_sp_func_num : dlx_sp_func_num;
|
98 |
|
|
variable instr_fp_func_num : dlx_fp_func_num;
|
99 |
|
|
variable rs1 : reg_index;
|
100 |
|
|
variable rs2 : reg_index;
|
101 |
|
|
variable Itype_rd : reg_index;
|
102 |
|
|
variable Rtype_rd : reg_index;
|
103 |
|
|
variable result : string(1 to 40) -- long enough for longest instruction
|
104 |
|
|
:= (others => ' ');
|
105 |
|
|
variable index : positive range 1 to 41 := 1; -- position for next char in result
|
106 |
|
|
|
107 |
|
|
procedure disassemble_reg ( reg : reg_index; reg_prefix : character ) is
|
108 |
|
|
begin
|
109 |
|
|
result(index) := reg_prefix;
|
110 |
|
|
index := index + 1;
|
111 |
|
|
if reg < 10 then
|
112 |
|
|
result(index to index) := integer'image(reg);
|
113 |
|
|
index := index + 1;
|
114 |
|
|
else
|
115 |
|
|
result(index to index + 1) := integer'image(reg);
|
116 |
|
|
index := index + 2;
|
117 |
|
|
end if;
|
118 |
|
|
end procedure disassemble_reg;
|
119 |
|
|
|
120 |
|
|
procedure disassemble_special_reg ( reg : reg_index ) is
|
121 |
|
|
begin
|
122 |
|
|
case reg is
|
123 |
|
|
when 0 =>
|
124 |
|
|
result(index to index + 2) := "IAR";
|
125 |
|
|
index := index + 3;
|
126 |
|
|
when 1 =>
|
127 |
|
|
result(index to index + 2) := "FSR";
|
128 |
|
|
index := index + 3;
|
129 |
|
|
when others =>
|
130 |
|
|
disassemble_reg(reg, 'S');
|
131 |
|
|
end case;
|
132 |
|
|
end procedure disassemble_special_reg;
|
133 |
|
|
|
134 |
|
|
procedure disassemble_integer ( int : integer ) is
|
135 |
|
|
constant int_image_length : natural := integer'image(int)'length;
|
136 |
|
|
begin
|
137 |
|
|
result(index to index + int_image_length - 1) := integer'image(int);
|
138 |
|
|
index := index + int_image_length;
|
139 |
|
|
end procedure disassemble_integer;
|
140 |
|
|
|
141 |
|
|
begin
|
142 |
|
|
instr_opcode_num := bv_to_natural(instr_opcode);
|
143 |
|
|
instr_sp_func_num := bv_to_natural(instr_sp_func);
|
144 |
|
|
instr_fp_func_num := bv_to_natural(instr_fp_func);
|
145 |
|
|
rs1 := bv_to_natural(instr_rs1);
|
146 |
|
|
rs2 := bv_to_natural(instr_rs2);
|
147 |
|
|
Itype_rd := bv_to_natural(instr_Itype_rd);
|
148 |
|
|
Rtype_rd := bv_to_natural(instr_Rtype_rd);
|
149 |
|
|
if (instr_opcode /= op_special) and (instr_opcode /= op_fparith) then
|
150 |
|
|
result(index to index + instr_name'length - 1) := opcode_names(instr_opcode_num);
|
151 |
|
|
index := index + instr_name'length + 1; -- include space after opcode name
|
152 |
|
|
end if;
|
153 |
|
|
case instr_opcode is
|
154 |
|
|
when op_special =>
|
155 |
|
|
result(index to index + instr_name'length - 1) := sp_func_names(instr_sp_func_num);
|
156 |
|
|
index := index + instr_name'length + 1; -- include space after function name
|
157 |
|
|
case instr_sp_func is
|
158 |
|
|
when sp_func_nop =>
|
159 |
|
|
null;
|
160 |
|
|
when sp_func_sll | sp_func_srl | sp_func_sra
|
161 |
|
|
| sp_func_sequ | sp_func_sneu | sp_func_sltu
|
162 |
|
|
| sp_func_sgtu | sp_func_sleu | sp_func_sgeu
|
163 |
|
|
| sp_func_add | sp_func_addu | sp_func_sub | sp_func_subu
|
164 |
|
|
| sp_func_and | sp_func_or | sp_func_xor
|
165 |
|
|
| sp_func_seq | sp_func_sne | sp_func_slt
|
166 |
|
|
| sp_func_sgt | sp_func_sle | sp_func_sge =>
|
167 |
|
|
disassemble_reg(Rtype_rd, 'R');
|
168 |
|
|
result(index) := ',';
|
169 |
|
|
index := index + 2; -- include space after comma
|
170 |
|
|
disassemble_reg(rs1, 'R');
|
171 |
|
|
result(index) := ',';
|
172 |
|
|
index := index + 2; -- include space after comma
|
173 |
|
|
disassemble_reg(rs2, 'R');
|
174 |
|
|
when sp_func_movi2s =>
|
175 |
|
|
disassemble_special_reg(Rtype_rd);
|
176 |
|
|
result(index) := ',';
|
177 |
|
|
index := index + 2; -- include space after comma
|
178 |
|
|
disassemble_reg(rs1, 'R');
|
179 |
|
|
when sp_func_movs2i =>
|
180 |
|
|
disassemble_reg(Rtype_rd, 'R');
|
181 |
|
|
result(index) := ',';
|
182 |
|
|
index := index + 2; -- include space after comma
|
183 |
|
|
disassemble_special_reg(rs1);
|
184 |
|
|
when sp_func_movf | sp_func_movd =>
|
185 |
|
|
disassemble_reg(Rtype_rd, 'F');
|
186 |
|
|
result(index) := ',';
|
187 |
|
|
index := index + 2; -- include space after comma
|
188 |
|
|
disassemble_reg(rs1, 'F');
|
189 |
|
|
when sp_func_movfp2i =>
|
190 |
|
|
disassemble_reg(Rtype_rd, 'R');
|
191 |
|
|
result(index) := ',';
|
192 |
|
|
index := index + 2; -- include space after comma
|
193 |
|
|
disassemble_reg(rs1, 'F');
|
194 |
|
|
when sp_func_movi2fp =>
|
195 |
|
|
disassemble_reg(Rtype_rd, 'F');
|
196 |
|
|
result(index) := ',';
|
197 |
|
|
index := index + 2; -- include space after comma
|
198 |
|
|
disassemble_reg(rs1, 'R');
|
199 |
|
|
when others =>
|
200 |
|
|
null;
|
201 |
|
|
end case;
|
202 |
|
|
when op_fparith =>
|
203 |
|
|
result(index to index + instr_name'length - 1) := fp_func_names(instr_fp_func_num);
|
204 |
|
|
index := index + instr_name'length + 1; -- include space after function name
|
205 |
|
|
case instr_fp_func is
|
206 |
|
|
when fp_func_addf | fp_func_subf | fp_func_multf | fp_func_divf
|
207 |
|
|
| fp_func_addd | fp_func_subd | fp_func_multd | fp_func_divd
|
208 |
|
|
| fp_func_mult | fp_func_div | fp_func_multu | fp_func_divu =>
|
209 |
|
|
disassemble_reg(Rtype_rd, 'F');
|
210 |
|
|
result(index) := ',';
|
211 |
|
|
index := index + 2; -- include space after comma
|
212 |
|
|
disassemble_reg(rs1, 'F');
|
213 |
|
|
result(index) := ',';
|
214 |
|
|
index := index + 2; -- include space after comma
|
215 |
|
|
disassemble_reg(rs2, 'F');
|
216 |
|
|
when fp_func_cvtf2d | fp_func_cvtd2f =>
|
217 |
|
|
disassemble_reg(Rtype_rd, 'F');
|
218 |
|
|
result(index) := ',';
|
219 |
|
|
index := index + 2; -- include space after comma
|
220 |
|
|
disassemble_reg(rs1, 'F');
|
221 |
|
|
when fp_func_cvtf2i | fp_func_cvtd2i =>
|
222 |
|
|
disassemble_reg(Rtype_rd, 'R');
|
223 |
|
|
result(index) := ',';
|
224 |
|
|
index := index + 2; -- include space after comma
|
225 |
|
|
disassemble_reg(rs1, 'F');
|
226 |
|
|
when fp_func_cvti2f | fp_func_cvti2d =>
|
227 |
|
|
disassemble_reg(Rtype_rd, 'F');
|
228 |
|
|
result(index) := ',';
|
229 |
|
|
index := index + 2; -- include space after comma
|
230 |
|
|
disassemble_reg(rs1, 'R');
|
231 |
|
|
when fp_func_eqf | fp_func_nef | fp_func_ltf
|
232 |
|
|
| fp_func_gtf | fp_func_lef | fp_func_gef
|
233 |
|
|
| fp_func_eqd | fp_func_ned | fp_func_ltd
|
234 |
|
|
| fp_func_gtd | fp_func_led | fp_func_ged =>
|
235 |
|
|
disassemble_reg(rs1, 'F');
|
236 |
|
|
result(index) := ',';
|
237 |
|
|
index := index + 2; -- include space after comma
|
238 |
|
|
disassemble_reg(rs2, 'F');
|
239 |
|
|
when others =>
|
240 |
|
|
null;
|
241 |
|
|
end case;
|
242 |
|
|
when op_j | op_jal =>
|
243 |
|
|
disassemble_integer(bv_to_integer(instr_immed26));
|
244 |
|
|
when op_beqz | op_bnez =>
|
245 |
|
|
disassemble_reg(rs1, 'R');
|
246 |
|
|
result(index) := ',';
|
247 |
|
|
index := index + 2; -- include space after comma
|
248 |
|
|
disassemble_integer(bv_to_integer(instr_immed16));
|
249 |
|
|
when op_bfpt | op_bfpf =>
|
250 |
|
|
disassemble_integer(bv_to_integer(instr_immed16));
|
251 |
|
|
when op_slli | op_srli | op_srai =>
|
252 |
|
|
disassemble_reg(Itype_rd, 'R');
|
253 |
|
|
result(index) := ',';
|
254 |
|
|
index := index + 2; -- include space after comma
|
255 |
|
|
disassemble_reg(rs1, 'R');
|
256 |
|
|
result(index) := ',';
|
257 |
|
|
index := index + 2; -- include space after comma
|
258 |
|
|
disassemble_integer(bv_to_natural(instr_immed16(11 to 15)));
|
259 |
|
|
when op_addi | op_subi
|
260 |
|
|
| op_seqi | op_snei | op_slti | op_sgti | op_slei | op_sgei =>
|
261 |
|
|
disassemble_reg(Itype_rd, 'R');
|
262 |
|
|
result(index) := ',';
|
263 |
|
|
index := index + 2; -- include space after comma
|
264 |
|
|
disassemble_reg(rs1, 'R');
|
265 |
|
|
result(index) := ',';
|
266 |
|
|
index := index + 2; -- include space after comma
|
267 |
|
|
disassemble_integer(bv_to_integer(instr_immed16));
|
268 |
|
|
when op_addui | op_subui | op_andi | op_ori | op_xori
|
269 |
|
|
| op_sequi | op_sneui | op_sltui | op_sgtui | op_sleui | op_sgeui =>
|
270 |
|
|
disassemble_reg(Itype_rd, 'R');
|
271 |
|
|
result(index) := ',';
|
272 |
|
|
index := index + 2; -- include space after comma
|
273 |
|
|
disassemble_reg(rs1, 'R');
|
274 |
|
|
result(index) := ',';
|
275 |
|
|
index := index + 2; -- include space after comma
|
276 |
|
|
disassemble_integer(bv_to_natural(instr_immed16));
|
277 |
|
|
when op_lhi =>
|
278 |
|
|
disassemble_reg(Itype_rd, 'R');
|
279 |
|
|
result(index) := ',';
|
280 |
|
|
index := index + 2; -- include space after comma
|
281 |
|
|
disassemble_integer(bv_to_natural(instr_immed16));
|
282 |
|
|
when op_rfe =>
|
283 |
|
|
null;
|
284 |
|
|
when op_trap =>
|
285 |
|
|
disassemble_integer(bv_to_natural(instr_immed26));
|
286 |
|
|
when op_jr | op_jalr =>
|
287 |
|
|
disassemble_reg(rs1, 'R');
|
288 |
|
|
when op_lb | op_lh | op_lw | op_lbu | op_lhu | op_lf | op_ld =>
|
289 |
|
|
disassemble_reg(Itype_rd, 'R');
|
290 |
|
|
result(index) := ',';
|
291 |
|
|
index := index + 2; -- include space after comma
|
292 |
|
|
disassemble_integer(bv_to_integer(instr_immed16));
|
293 |
|
|
result(index) := '(';
|
294 |
|
|
index := index + 1;
|
295 |
|
|
disassemble_reg(rs1, 'R');
|
296 |
|
|
result(index) := ')';
|
297 |
|
|
index := index + 1;
|
298 |
|
|
when op_sb | op_sh | op_sw | op_sf | op_sd =>
|
299 |
|
|
disassemble_integer(bv_to_integer(instr_immed16));
|
300 |
|
|
result(index) := '(';
|
301 |
|
|
index := index + 1;
|
302 |
|
|
disassemble_reg(rs1, 'R');
|
303 |
|
|
result(index) := ')';
|
304 |
|
|
index := index + 1;
|
305 |
|
|
result(index) := ',';
|
306 |
|
|
index := index + 2; -- include space after comma
|
307 |
|
|
disassemble_reg(Itype_rd, 'R');
|
308 |
|
|
when others =>
|
309 |
|
|
null; -- remaining opcodes have no operands to disassemble
|
310 |
|
|
end case;
|
311 |
|
|
if index > norm_disassembled_instr'length then
|
312 |
|
|
index := norm_disassembled_instr'length; -- limit to out parameter length
|
313 |
|
|
else
|
314 |
|
|
index := index - 1; -- index points to last result character
|
315 |
|
|
end if;
|
316 |
|
|
norm_disassembled_instr(1 to index) := result(1 to index);
|
317 |
|
|
len := index;
|
318 |
|
|
end procedure disassemble;
|
319 |
|
|
|
320 |
|
|
end package body dlx_instr;
|