blob: 8141095a2db5d74e2b8c1a9d495c94387a45be1e [file] [log] [blame]
Andrew Geissler84ad7c52020-06-27 00:00:16 -05001From 7b332d61cb3dbcae69021ce706f2c408c85af193 Mon Sep 17 00:00:00 2001
2From: Nagaraju <nmekala@xilinx.com>
3Date: Fri, 23 Aug 2019 16:18:43 +0530
4Subject: [PATCH 30/43] Added support to new arithmetic single register
5 instructions
6
7---
8 gas/config/tc-microblaze.c | 147 ++++++++++++++++++++++++++++++++++++-
9 opcodes/microblaze-dis.c | 12 +++
10 opcodes/microblaze-opc.h | 43 ++++++++++-
11 opcodes/microblaze-opcm.h | 5 +-
12 4 files changed, 201 insertions(+), 6 deletions(-)
13
14diff --git a/gas/config/tc-microblaze.c b/gas/config/tc-microblaze.c
15index 5b506d3348..12eef24a29 100644
16--- a/gas/config/tc-microblaze.c
17+++ b/gas/config/tc-microblaze.c
18@@ -423,12 +423,33 @@ void
19 md_begin (void)
20 {
21 struct op_code_struct * opcode;
22+ const char *prev_name = "";
23
24 opcode_hash_control = hash_new ();
25
26 /* Insert unique names into hash table. */
27- for (opcode = opcodes; opcode->name; opcode ++)
28- hash_insert (opcode_hash_control, opcode->name, (char *) opcode);
29+ for (opcode = (struct opcodes *)opcodes; opcode->name; opcode ++)
30+ {
31+ if (strcmp (prev_name, opcode->name))
32+ {
33+ prev_name = (char *) opcode->name;
34+ hash_insert (opcode_hash_control, opcode->name, (char *) opcode);
35+ }
36+ }
37+}
38+
39+static int
40+is_reg (char * s)
41+{
42+ int is_reg = 0;
43+ /* Strip leading whitespace. */
44+ while (ISSPACE (* s))
45+ ++ s;
46+ if (TOLOWER (s[0]) == 'r')
47+ {
48+ is_reg =1;
49+ }
50+ return is_reg;
51 }
52
53 /* Try to parse a reg name. */
54@@ -986,6 +1007,7 @@ md_assemble (char * str)
55 {
56 char * op_start;
57 char * op_end;
58+ char * temp_op_end;
59 struct op_code_struct * opcode, *opcode1;
60 char * output = NULL;
61 int nlen = 0;
62@@ -996,9 +1018,10 @@ md_assemble (char * str)
63 unsigned reg3;
64 unsigned isize;
65 unsigned long immed, immed2, temp;
66- expressionS exp;
67+ expressionS exp,exp1;
68 char name[20];
69 long immedl;
70+ int reg=0;
71
72 /* Drop leading whitespace. */
73 while (ISSPACE (* str))
74@@ -1029,7 +1052,78 @@ md_assemble (char * str)
75 as_bad (_("unknown opcode \"%s\""), name);
76 return;
77 }
78-
79+
80+ if ((microblaze_arch_size == 64) && (streq (name, "addli") || streq (name, "addlic") ||
81+ streq (name, "addlik") || streq (name, "addlikc") || streq (name, "rsubli")
82+ || streq (name, "rsublic") || streq (name, "rsublik") || streq (name, "rsublikc")
83+ || streq (name, "andli") || streq (name, "andnli") || streq (name, "orli")
84+ || streq (name, "xorli")))
85+ {
86+ temp_op_end = op_end;
87+ if (strcmp (temp_op_end, ""))
88+ temp_op_end = parse_reg (temp_op_end + 1, &reg1); /* Get rd. */
89+ if (strcmp (temp_op_end, ""))
90+ reg = is_reg (temp_op_end + 1);
91+ if (reg)
92+ {
93+
94+ opcode->inst_type=INST_TYPE_RD_R1_IMML;
95+ opcode->inst_offset_type = OPCODE_MASK_H;
96+ if (streq (name, "addli"))
97+ opcode->bit_sequence = ADDLI_MASK;
98+ else if (streq (name, "addlic"))
99+ opcode->bit_sequence = ADDLIC_MASK;
100+ else if (streq (name, "addlik"))
101+ opcode->bit_sequence = ADDLIK_MASK;
102+ else if (streq (name, "addlikc"))
103+ opcode->bit_sequence = ADDLIKC_MASK;
104+ else if (streq (name, "rsubli"))
105+ opcode->bit_sequence = RSUBLI_MASK;
106+ else if (streq (name, "rsublic"))
107+ opcode->bit_sequence = RSUBLIC_MASK;
108+ else if (streq (name, "rsublik"))
109+ opcode->bit_sequence = RSUBLIK_MASK;
110+ else if (streq (name, "rsublikc"))
111+ opcode->bit_sequence = RSUBLIKC_MASK;
112+ else if (streq (name, "andli"))
113+ opcode->bit_sequence = ANDLI_MASK;
114+ else if (streq (name, "andnli"))
115+ opcode->bit_sequence = ANDLNI_MASK;
116+ else if (streq (name, "orli"))
117+ opcode->bit_sequence = ORLI_MASK;
118+ else if (streq (name, "xorli"))
119+ opcode->bit_sequence = XORLI_MASK;
120+ }
121+ else
122+ {
123+ opcode->inst_type=INST_TYPE_RD_IMML;
124+ opcode->inst_offset_type = OPCODE_MASK_LIMM;
125+ if (streq (name, "addli"))
126+ opcode->bit_sequence = ADDLI_ONE_REG_MASK;
127+ else if (streq (name, "addlic"))
128+ opcode->bit_sequence = ADDLIC_ONE_REG_MASK;
129+ else if (streq (name, "addlik"))
130+ opcode->bit_sequence = ADDLIK_ONE_REG_MASK;
131+ else if (streq (name, "addlikc"))
132+ opcode->bit_sequence = ADDLIKC_ONE_REG_MASK;
133+ else if (streq (name, "rsubli"))
134+ opcode->bit_sequence = RSUBLI_ONE_REG_MASK;
135+ else if (streq (name, "rsublic"))
136+ opcode->bit_sequence = RSUBLIC_ONE_REG_MASK;
137+ else if (streq (name, "rsublik"))
138+ opcode->bit_sequence = RSUBLIK_ONE_REG_MASK;
139+ else if (streq (name, "rsublikc"))
140+ opcode->bit_sequence = RSUBLIKC_ONE_REG_MASK;
141+ else if (streq (name, "andli"))
142+ opcode->bit_sequence = ANDLI_ONE_REG_MASK;
143+ else if (streq (name, "andnli"))
144+ opcode->bit_sequence = ANDLNI_ONE_REG_MASK;
145+ else if (streq (name, "orli"))
146+ opcode->bit_sequence = ORLI_ONE_REG_MASK;
147+ else if (streq (name, "xorli"))
148+ opcode->bit_sequence = XORLI_ONE_REG_MASK;
149+ }
150+ }
151 inst = opcode->bit_sequence;
152 isize = 4;
153
154@@ -1480,6 +1574,51 @@ md_assemble (char * str)
155 inst |= (immed << IMM_LOW) & IMM15_MASK;
156 break;
157
158+ case INST_TYPE_RD_IMML:
159+ if (strcmp (op_end, ""))
160+ op_end = parse_reg (op_end + 1, &reg1); /* Get rd. */
161+ else
162+ {
163+ as_fatal (_("Error in statement syntax"));
164+ reg1 = 0;
165+ }
166+
167+ if (strcmp (op_end, ""))
168+ op_end = parse_imml (op_end + 1, & exp, MIN_IMML, MAX_IMML);
169+ else
170+ as_fatal (_("Error in statement syntax"));
171+
172+ /* Check for spl registers. */
173+ if (check_spl_reg (&reg1))
174+ as_fatal (_("Cannot use special register with this instruction"));
175+ if (exp.X_op != O_constant)
176+ {
177+ char *opc = NULL;
178+ relax_substateT subtype;
179+
180+ if (exp.X_md != 0)
181+ subtype = get_imm_otype(exp.X_md);
182+ else
183+ subtype = opcode->inst_offset_type;
184+
185+ output = frag_var (rs_machine_dependent,
186+ isize * 2,
187+ isize * 2,
188+ subtype,
189+ exp.X_add_symbol,
190+ exp.X_add_number,
191+ (char *) opc);
192+ immedl = 0L;
193+ }
194+ else
195+ {
196+ output = frag_more (isize);
197+ immed = exp.X_add_number;
198+ }
199+ inst |= (reg1 << RD_LOW) & RD_MASK;
200+ inst |= (immed << IMM_LOW) & IMM16_MASK;
201+ break;
202+
203 case INST_TYPE_R1_RFSL:
204 if (strcmp (op_end, ""))
205 op_end = parse_reg (op_end + 1, &reg1); /* Get r1. */
206diff --git a/opcodes/microblaze-dis.c b/opcodes/microblaze-dis.c
207index f679a43606..e5e880cb1c 100644
208--- a/opcodes/microblaze-dis.c
209+++ b/opcodes/microblaze-dis.c
210@@ -114,6 +114,15 @@ get_field_imm15 (long instr)
211 return (strdup (tmpstr));
212 }
213
214+static char *
215+get_field_imm16 (long instr)
216+{
217+ char tmpstr[25];
218+
219+ sprintf (tmpstr, "%d", (short)((instr & IMM16_MASK) >> IMM_LOW));
220+ return (strdup (tmpstr));
221+}
222+
223 static char *
224 get_field_special (long instr, struct op_code_struct * op)
225 {
226@@ -419,6 +428,9 @@ print_insn_microblaze (bfd_vma memaddr, struct disassemble_info * info)
227 case INST_TYPE_RD_IMM15:
228 print_func (stream, "\t%s, %s", get_field_rd (inst), get_field_imm15 (inst));
229 break;
230+ case INST_TYPE_RD_IMML:
231+ print_func (stream, "\t%s, %s", get_field_rd (inst), get_field_imm16 (inst));
232+ break;
233 /* For mbar insn. */
234 case INST_TYPE_IMM5:
235 print_func (stream, "\t%s", get_field_imm5_mbar (inst));
236diff --git a/opcodes/microblaze-opc.h b/opcodes/microblaze-opc.h
237index d59ee0a95f..0774f70e08 100644
238--- a/opcodes/microblaze-opc.h
239+++ b/opcodes/microblaze-opc.h
240@@ -69,6 +69,7 @@
241 #define INST_TYPE_RD_R1_IMMW_IMMS 21
242
243 #define INST_TYPE_NONE 25
244+#define INST_TYPE_RD_IMML 26
245
246
247
248@@ -84,6 +85,7 @@
249 #define IMMVAL_MASK_MFS 0x0000
250
251 #define OPCODE_MASK_H 0xFC000000 /* High 6 bits only. */
252+#define OPCODE_MASK_LIMM 0xFC1F0000 /* High 6 bits and 12-16 bits */
253 #define OPCODE_MASK_H1 0xFFE00000 /* High 11 bits. */
254 #define OPCODE_MASK_H2 0xFC1F0000 /* High 6 and bits 20-16. */
255 #define OPCODE_MASK_H12 0xFFFF0000 /* High 16. */
256@@ -106,6 +108,33 @@
257 #define OPCODE_MASK_H34C 0xFC0007E0 /* High 6 bits and bits 21-26. */
258 #define OPCODE_MASK_H8 0xFF000000 /* High 8 bits only. */
259
260+/*Defines to identify 64-bit single reg instructions */
261+#define ADDLI_ONE_REG_MASK 0x68000000
262+#define ADDLIC_ONE_REG_MASK 0x68020000
263+#define ADDLIK_ONE_REG_MASK 0x68040000
264+#define ADDLIKC_ONE_REG_MASK 0x68060000
265+#define RSUBLI_ONE_REG_MASK 0x68010000
266+#define RSUBLIC_ONE_REG_MASK 0x68030000
267+#define RSUBLIK_ONE_REG_MASK 0x68050000
268+#define RSUBLIKC_ONE_REG_MASK 0x68070000
269+#define ORLI_ONE_REG_MASK 0x68100000
270+#define ANDLI_ONE_REG_MASK 0x68110000
271+#define XORLI_ONE_REG_MASK 0x68120000
272+#define ANDLNI_ONE_REG_MASK 0x68130000
273+#define ADDLI_MASK 0x20000000
274+#define ADDLIC_MASK 0x28000000
275+#define ADDLIK_MASK 0x30000000
276+#define ADDLIKC_MASK 0x38000000
277+#define RSUBLI_MASK 0x24000000
278+#define RSUBLIC_MASK 0x2C000000
279+#define RSUBLIK_MASK 0x34000000
280+#define RSUBLIKC_MASK 0x3C000000
281+#define ANDLI_MASK 0xA4000000
282+#define ANDLNI_MASK 0xAC000000
283+#define ORLI_MASK 0xA0000000
284+#define XORLI_MASK 0xA8000000
285+
286+
287 /* New Mask for msrset, msrclr insns. */
288 #define OPCODE_MASK_H23N 0xFC1F8000 /* High 6 and bits 11 - 16. */
289 /* Mask for mbar insn. */
290@@ -114,7 +143,7 @@
291 #define DELAY_SLOT 1
292 #define NO_DELAY_SLOT 0
293
294-#define MAX_OPCODES 412
295+#define MAX_OPCODES 424
296
297 struct op_code_struct
298 {
299@@ -444,13 +473,21 @@ struct op_code_struct
300 {"cmpl", INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x14000101, OPCODE_MASK_H4, cmpl, arithmetic_inst },
301 {"cmplu", INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x14000103, OPCODE_MASK_H4, cmplu, arithmetic_inst },
302 {"addli", INST_TYPE_RD_R1_IMML, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x20000000, OPCODE_MASK_H, invalid_inst, arithmetic_inst }, /* Identical to 32-bit */
303+ {"addli", INST_TYPE_RD_IMML, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL,0x68000000, OPCODE_MASK_LIMM, addli, arithmetic_inst },
304 {"rsubli", INST_TYPE_RD_R1_IMML, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x24000000, OPCODE_MASK_H, invalid_inst, arithmetic_inst }, /* Identical to 32-bit */
305+ {"rsubli", INST_TYPE_RD_IMML, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL,0x68010000, OPCODE_MASK_LIMM, rsubli, arithmetic_inst },
306 {"addlic", INST_TYPE_RD_R1_IMML, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x28000000, OPCODE_MASK_H, invalid_inst, arithmetic_inst }, /* Identical to 32-bit */
307+ {"addlic", INST_TYPE_RD_IMML, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL,0x68020000, OPCODE_MASK_LIMM, addlic, arithmetic_inst },
308 {"rsublic", INST_TYPE_RD_R1_IMML, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x2C000000, OPCODE_MASK_H, invalid_inst, arithmetic_inst }, /* Identical to 32-bit */
309+ {"rsublic", INST_TYPE_RD_IMML, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL,0x68030000, OPCODE_MASK_LIMM, rsublic, arithmetic_inst },
310 {"addlik", INST_TYPE_RD_R1_IMML, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x30000000, OPCODE_MASK_H, invalid_inst, arithmetic_inst }, /* Identical to 32-bit */
311+ {"addlik", INST_TYPE_RD_IMML, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL,0x68040000, OPCODE_MASK_LIMM, addlik, arithmetic_inst },
312 {"rsublik", INST_TYPE_RD_R1_IMML, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x34000000, OPCODE_MASK_H, invalid_inst, arithmetic_inst }, /* Identical to 32-bit */
313+ {"rsublik", INST_TYPE_RD_IMML, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL,0x68050000, OPCODE_MASK_LIMM, rsublik, arithmetic_inst },
314 {"addlikc", INST_TYPE_RD_R1_IMML, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x38000000, OPCODE_MASK_H, invalid_inst, arithmetic_inst }, /* Identical to 32-bit */
315+ {"addlikc", INST_TYPE_RD_IMML, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL,0x68060000, OPCODE_MASK_LIMM, addlikc, arithmetic_inst },
316 {"rsublikc",INST_TYPE_RD_R1_IMML, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x3C000000, OPCODE_MASK_H, invalid_inst, arithmetic_inst }, /* Identical to 32-bit */
317+ {"rsublikc", INST_TYPE_RD_IMML, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL,0x68070000, OPCODE_MASK_LIMM, rsublikc, arithmetic_inst },
318 {"mull", INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x40000100, OPCODE_MASK_H4, mull, mult_inst },
319 {"bslll", INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x44000500, OPCODE_MASK_H3, bslll, barrel_shift_inst },
320 {"bslra", INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x44000300, OPCODE_MASK_H3, bslra, barrel_shift_inst },
321@@ -501,9 +538,13 @@ struct op_code_struct
322 {"beaged", INST_TYPE_R1_R2, INST_PC_OFFSET, DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x9FA00000, OPCODE_MASK_H14, beaged, branch_inst },
323 {"bealged", INST_TYPE_R1_R2, INST_PC_OFFSET, DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x9FA00100, OPCODE_MASK_H14, bealged, branch_inst },
324 {"orli", INST_TYPE_RD_R1_IMML, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xA0000000, OPCODE_MASK_H, invalid_inst, logical_inst }, /* Identical to 32-bit */
325+ {"orli", INST_TYPE_RD_IMML, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL,0x68100000, OPCODE_MASK_LIMM, orli, arithmetic_inst },
326 {"andli", INST_TYPE_RD_R1_IMML, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xA4000000, OPCODE_MASK_H, invalid_inst, logical_inst }, /* Identical to 32-bit */
327+ {"andli", INST_TYPE_RD_IMML, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL,0x68110000, OPCODE_MASK_LIMM, andli, arithmetic_inst },
328 {"xorli", INST_TYPE_RD_R1_IMML, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xA8000000, OPCODE_MASK_H, invalid_inst, logical_inst }, /* Identical to 32-bit */
329+ {"xorli", INST_TYPE_RD_IMML, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL,0x68120000, OPCODE_MASK_LIMM, xorli, arithmetic_inst },
330 {"andnli", INST_TYPE_RD_R1_IMML, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xAC000000, OPCODE_MASK_H, invalid_inst, logical_inst }, /* Identical to 32-bit */
331+ {"andnli", INST_TYPE_RD_IMML, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL,0x68130000, OPCODE_MASK_LIMM, andnli, arithmetic_inst },
332 {"imml", INST_TYPE_IMML, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xB2000000, OPCODE_MASK_H8, imml, immediate_inst },
333 {"breai", INST_TYPE_IMM, INST_PC_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xB8010000, OPCODE_MASK_H12, breai, branch_inst },
334 {"breaid", INST_TYPE_IMM, INST_PC_OFFSET, DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xB8110000, OPCODE_MASK_H12, breaid, branch_inst },
335diff --git a/opcodes/microblaze-opcm.h b/opcodes/microblaze-opcm.h
336index 5f2e190d23..4d2ee2dd0d 100644
337--- a/opcodes/microblaze-opcm.h
338+++ b/opcodes/microblaze-opcm.h
339@@ -61,7 +61,9 @@ enum microblaze_instr
340 eaputd, teaputd, ecaputd, tecaputd, neaputd, tneaputd, necaputd, tnecaputd,
341
342 /* 64-bit instructions */
343- addl, rsubl, addlc, rsublc, addlk, rsublk, addlkc, rsublkc, cmpl, cmplu, mull,
344+ addl, addli, addlic, addlik, addlikc, rsubl, rsubli, rsublic, rsublik, rsublikc,
345+ addlc, rsublc, addlk, rsublk, addlkc, rsublkc, cmpl, cmplu, mull,
346+ andli, andnli, orli, xorli,
347 bslll, bslra, bslrl, bsllli, bslrai, bslrli, bslefi, bslifi, orl, andl, xorl,
348 andnl, pcmplbf, pcmpleq, pcmplne, srla, srlc, srll, sextl8, sextl16, sextl32,
349 brea, bread, breald, beaeq, bealeq, beaeqd, bealeqd, beane, bealne, beaned,
350@@ -166,5 +168,6 @@ enum microblaze_instr_type
351
352 /* Imm mask for msrset, msrclr instructions. */
353 #define IMM15_MASK 0x00007FFF
354+#define IMM16_MASK 0x0000FFFF
355
356 #endif /* MICROBLAZE-OPCM */
357--
3582.17.1
359