xref: /netbsd-src/external/gpl3/gcc.old/dist/gcc/config/moxie/moxie.md (revision eceb233b9bd0dfebb902ed73b531ae6964fa3f9b)
1;; Machine description for Moxie
2;; Copyright (C) 2009-2018 Free Software Foundation, Inc.
3;; Contributed by Anthony Green <green@moxielogic.com>
4
5;; This file is part of GCC.
6
7;; GCC is free software; you can redistribute it and/or modify it
8;; under the terms of the GNU General Public License as published
9;; by the Free Software Foundation; either version 3, or (at your
10;; option) any later version.
11
12;; GCC is distributed in the hope that it will be useful, but WITHOUT
13;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14;; or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
15;; License for more details.
16
17;; You should have received a copy of the GNU General Public License
18;; along with GCC; see the file COPYING3.  If not see
19;; <http://www.gnu.org/licenses/>.
20
21;; -------------------------------------------------------------------------
22;; Moxie specific constraints, predicates and attributes
23;; -------------------------------------------------------------------------
24
25(include "constraints.md")
26(include "predicates.md")
27
28; Most instructions are two bytes long.
29(define_attr "length" "" (const_int 2))
30
31;; -------------------------------------------------------------------------
32;; nop instruction
33;; -------------------------------------------------------------------------
34
35(define_insn "nop"
36  [(const_int 0)]
37  ""
38  "nop")
39
40;; -------------------------------------------------------------------------
41;; Arithmetic instructions
42;; -------------------------------------------------------------------------
43
44(define_insn "addsi3"
45  [(set (match_operand:SI 0 "register_operand" "=r,r,r")
46	  (plus:SI
47	   (match_operand:SI 1 "register_operand" "0,0,0")
48	   (match_operand:SI 2 "moxie_add_operand" "I,N,r")))]
49  ""
50  "@
51  inc\\t%0, %2
52  dec\\t%0, -%2
53  add\\t%0, %2")
54
55(define_insn "subsi3"
56  [(set (match_operand:SI 0 "register_operand" "=r,r")
57	  (minus:SI
58	   (match_operand:SI 1 "register_operand" "0,0")
59	   (match_operand:SI 2 "moxie_sub_operand" "I,r")))]
60  ""
61  "@
62  dec\\t%0, %2
63  sub\\t%0, %2")
64
65(define_insn "mulsi3"
66  [(set (match_operand:SI 0 "register_operand" "=r")
67	  (mult:SI
68	   (match_operand:SI 1 "register_operand" "0")
69	   (match_operand:SI 2 "register_operand" "r")))]
70  ""
71  "mul\\t%0, %2")
72
73(define_code_iterator EXTEND [sign_extend zero_extend])
74(define_code_attr mul [(sign_extend "mul") (zero_extend "umul")])
75
76(define_insn "<mul>si3_highpart"
77  [(set (match_operand:SI 0 "register_operand"                       "=r")
78        (truncate:SI
79         (lshiftrt:DI
80          (mult:DI (EXTEND:DI (match_operand:SI 1 "register_operand"  "0"))
81                   (EXTEND:DI (match_operand:SI 2 "register_operand"  "r")))
82          (const_int 32))))]
83  "TARGET_HAS_MULX"
84  "<mul>.x\\t%0, %2")
85
86(define_expand "<mul>sidi3"
87  [(set (match_operand:DI 0 "register_operand" "")
88	(mult:DI (EXTEND:DI (match_operand:SI 1 "register_operand" "0"))
89		 (EXTEND:DI (match_operand:SI 2 "register_operand" "r"))))]
90  "TARGET_HAS_MULX"
91{
92  rtx hi = gen_reg_rtx (SImode);
93  rtx lo = gen_reg_rtx (SImode);
94
95  emit_insn (gen_<mul>si3_highpart (hi, operands[1], operands[2]));
96  emit_insn (gen_mulsi3 (lo, operands[1], operands[2]));
97  emit_move_insn (gen_lowpart (SImode, operands[0]), lo);
98  emit_move_insn (gen_highpart (SImode, operands[0]), hi);
99  DONE;
100})
101
102(define_insn "divsi3"
103  [(set (match_operand:SI 0 "register_operand" "=r")
104	  (div:SI
105	   (match_operand:SI 1 "register_operand" "0")
106	   (match_operand:SI 2 "register_operand" "r")))]
107  ""
108  "div\\t%0, %2")
109
110(define_insn "udivsi3"
111  [(set (match_operand:SI 0 "register_operand" "=r")
112	  (udiv:SI
113	   (match_operand:SI 1 "register_operand" "0")
114	   (match_operand:SI 2 "register_operand" "r")))]
115  ""
116  "udiv\\t%0, %2")
117
118(define_insn "modsi3"
119  [(set (match_operand:SI 0 "register_operand" "=r")
120	  (mod:SI
121	   (match_operand:SI 1 "register_operand" "0")
122	   (match_operand:SI 2 "register_operand" "r")))]
123  ""
124  "mod\\t%0, %2")
125
126(define_insn "umodsi3"
127  [(set (match_operand:SI 0 "register_operand" "=r")
128	  (umod:SI
129	   (match_operand:SI 1 "register_operand" "0")
130	   (match_operand:SI 2 "register_operand" "r")))]
131  ""
132  "umod\\t%0, %2")
133
134;; -------------------------------------------------------------------------
135;; Unary arithmetic instructions
136;; -------------------------------------------------------------------------
137
138(define_insn "negsi2"
139  [(set (match_operand:SI 0 "register_operand" "=r")
140	  (neg:SI (match_operand:SI 1 "register_operand" "r")))]
141  ""
142  "neg\\t%0, %1")
143
144(define_insn "one_cmplsi2"
145  [(set (match_operand:SI 0 "register_operand" "=r")
146	(not:SI (match_operand:SI 1 "register_operand" "r")))]
147  ""
148  "not\\t%0, %1")
149
150;; -------------------------------------------------------------------------
151;; Logical operators
152;; -------------------------------------------------------------------------
153
154(define_insn "andsi3"
155  [(set (match_operand:SI 0 "register_operand" "=r")
156	(and:SI (match_operand:SI 1 "register_operand" "0")
157		(match_operand:SI 2 "register_operand" "r")))]
158  ""
159{
160  return "and\\t%0, %2";
161})
162
163(define_insn "xorsi3"
164  [(set (match_operand:SI 0 "register_operand" "=r")
165	(xor:SI (match_operand:SI 1 "register_operand" "0")
166		(match_operand:SI 2 "register_operand" "r")))]
167  ""
168{
169  return "xor\\t%0, %2";
170})
171
172(define_insn "iorsi3"
173  [(set (match_operand:SI 0 "register_operand" "=r")
174	(ior:SI (match_operand:SI 1 "register_operand" "0")
175		(match_operand:SI 2 "register_operand" "r")))]
176  ""
177{
178  return "or\\t%0, %2";
179})
180
181;; -------------------------------------------------------------------------
182;; Shifters
183;; -------------------------------------------------------------------------
184
185(define_insn "ashlsi3"
186  [(set (match_operand:SI 0 "register_operand" "=r")
187	(ashift:SI (match_operand:SI 1 "register_operand" "0")
188		   (match_operand:SI 2 "register_operand" "r")))]
189  ""
190{
191  return "ashl\\t%0, %2";
192})
193
194(define_insn "ashrsi3"
195  [(set (match_operand:SI 0 "register_operand" "=r")
196	(ashiftrt:SI (match_operand:SI 1 "register_operand" "0")
197		     (match_operand:SI 2 "register_operand" "r")))]
198  ""
199{
200  return "ashr\\t%0, %2";
201})
202
203(define_insn "lshrsi3"
204  [(set (match_operand:SI 0 "register_operand" "=r")
205	(lshiftrt:SI (match_operand:SI 1 "register_operand" "0")
206		     (match_operand:SI 2 "register_operand" "r")))]
207  ""
208{
209  return "lshr\\t%0, %2";
210})
211
212;; -------------------------------------------------------------------------
213;; Move instructions
214;; -------------------------------------------------------------------------
215
216;; SImode
217
218;; Push a register onto the stack
219(define_insn "movsi_push"
220  [(set (mem:SI (pre_dec:SI (reg:SI 1)))
221  	(match_operand:SI 0 "register_operand" "r"))]
222  ""
223  "push\\t$sp, %0")
224
225;; Pop a register from the stack
226(define_insn "movsi_pop"
227  [(set (match_operand:SI 1 "register_operand" "=r")
228  	(mem:SI (post_inc:SI (match_operand:SI 0 "register_operand" "r"))))]
229  ""
230  "pop\\t%0, %1")
231
232(define_expand "movsi"
233   [(set (match_operand:SI 0 "general_operand" "")
234 	(match_operand:SI 1 "general_operand" ""))]
235   ""
236  "
237{
238  /* If this is a store, force the value into a register.  */
239  if (! (reload_in_progress || reload_completed))
240  {
241    if (MEM_P (operands[0]))
242    {
243      operands[1] = force_reg (SImode, operands[1]);
244      if (MEM_P (XEXP (operands[0], 0)))
245        operands[0] = gen_rtx_MEM (SImode, force_reg (SImode, XEXP (operands[0], 0)));
246    }
247    else
248      if (MEM_P (operands[1])
249          && MEM_P (XEXP (operands[1], 0)))
250        operands[1] = gen_rtx_MEM (SImode, force_reg (SImode, XEXP (operands[1], 0)));
251  }
252}")
253
254(define_insn "*movsi"
255  [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r,W,A,r,r,B,r")
256	(match_operand:SI 1 "moxie_general_movsrc_operand" "O,r,i,r,r,W,A,r,B"))]
257  "register_operand (operands[0], SImode)
258   || register_operand (operands[1], SImode)"
259  "@
260   xor\\t%0, %0
261   mov\\t%0, %1
262   ldi.l\\t%0, %1
263   st.l\\t%0, %1
264   sta.l\\t%0, %1
265   ld.l\\t%0, %1
266   lda.l\\t%0, %1
267   sto.l\\t%0, %1
268   ldo.l\\t%0, %1"
269  [(set_attr "length"	"2,2,6,2,6,2,6,4,4")])
270
271(define_insn "zero_extendqisi2"
272  [(set (match_operand:SI 0 "register_operand" "=r,r,r,r")
273	(zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,W,A,B")))]
274  ""
275  "@
276   zex.b\\t%0, %1
277   ld.b\\t%0, %1
278   lda.b\\t%0, %1
279   ldo.b\\t%0, %1"
280  [(set_attr "length" "2,2,6,4")])
281
282(define_insn "zero_extendhisi2"
283  [(set (match_operand:SI 0 "register_operand" "=r,r,r,r")
284	(zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,W,A,B")))]
285  ""
286  "@
287   zex.s\\t%0, %1
288   ld.s\\t%0, %1
289   lda.s\\t%0, %1
290   ldo.s\\t%0, %1"
291  [(set_attr "length" "2,2,6,4")])
292
293(define_insn "extendqisi2"
294  [(set (match_operand:SI 0 "register_operand" "=r")
295	(sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r")))]
296  ""
297  "@
298   sex.b\\t%0, %1"
299  [(set_attr "length" "2")])
300
301(define_insn "extendhisi2"
302  [(set (match_operand:SI 0 "register_operand" "=r")
303	(sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r")))]
304  ""
305  "@
306   sex.s\\t%0, %1"
307  [(set_attr "length" "2")])
308
309(define_expand "movqi"
310  [(set (match_operand:QI 0 "general_operand" "")
311	(match_operand:QI 1 "general_operand" ""))]
312  ""
313  "
314{
315  /* If this is a store, force the value into a register.  */
316  if (MEM_P (operands[0]))
317    operands[1] = force_reg (QImode, operands[1]);
318}")
319
320(define_insn "*movqi"
321  [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,W,A,r,r,B,r")
322	(match_operand:QI 1 "moxie_general_movsrc_operand" "O,r,i,r,r,W,A,r,B"))]
323  "register_operand (operands[0], QImode)
324   || register_operand (operands[1], QImode)"
325  "@
326   xor\\t%0, %0
327   mov\\t%0, %1
328   ldi.b\\t%0, %1
329   st.b\\t%0, %1
330   sta.b\\t%0, %1
331   ld.b\\t%0, %1
332   lda.b\\t%0, %1
333   sto.b\\t%0, %1
334   ldo.b\\t%0, %1"
335  [(set_attr "length"	"2,2,6,2,6,2,6,4,4")])
336
337(define_expand "movhi"
338  [(set (match_operand:HI 0 "general_operand" "")
339	(match_operand:HI 1 "general_operand" ""))]
340  ""
341  "
342{
343  /* If this is a store, force the value into a register.  */
344  if (MEM_P (operands[0]))
345    operands[1] = force_reg (HImode, operands[1]);
346}")
347
348(define_insn "*movhi"
349  [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,r,W,A,r,r,B,r")
350	(match_operand:HI 1 "moxie_general_movsrc_operand" "O,r,i,r,r,W,A,r,B"))]
351  "(register_operand (operands[0], HImode)
352    || register_operand (operands[1], HImode))"
353  "@
354   xor\\t%0, %0
355   mov\\t%0, %1
356   ldi.s\\t%0, %1
357   st.s\\t%0, %1
358   sta.s\\t%0, %1
359   ld.s\\t%0, %1
360   lda.s\\t%0, %1
361   sto.s\\t%0, %1
362   ldo.s\\t%0, %1"
363  [(set_attr "length"	"2,2,6,2,6,2,6,4,4")])
364
365;; -------------------------------------------------------------------------
366;; Compare instructions
367;; -------------------------------------------------------------------------
368
369(define_constants
370  [(CC_REG 19)])
371
372(define_expand "cbranchsi4"
373  [(set (reg:CC CC_REG)
374        (compare:CC
375         (match_operand:SI 1 "general_operand" "")
376         (match_operand:SI 2 "general_operand" "")))
377   (set (pc)
378        (if_then_else (match_operator 0 "comparison_operator"
379                       [(reg:CC CC_REG) (const_int 0)])
380                      (label_ref (match_operand 3 "" ""))
381                      (pc)))]
382  ""
383  "
384  /* Force the compare operands into registers.  */
385  if (GET_CODE (operands[1]) != REG)
386	operands[1] = force_reg (SImode, operands[1]);
387  if (GET_CODE (operands[2]) != REG)
388	operands[2] = force_reg (SImode, operands[2]);
389  ")
390
391(define_insn "*cmpsi"
392  [(set (reg:CC CC_REG)
393	(compare
394	 (match_operand:SI 0 "register_operand" "r")
395	 (match_operand:SI 1 "register_operand"	"r")))]
396  ""
397  "cmp\\t%0, %1")
398
399
400;; -------------------------------------------------------------------------
401;; Branch instructions
402;; -------------------------------------------------------------------------
403
404(define_code_iterator cond [ne eq lt ltu gt gtu ge le geu leu])
405(define_code_attr CC [(ne "ne") (eq "eq") (lt "lt") (ltu "ltu")
406		      (gt "gt") (gtu "gtu") (ge "ge") (le "le")
407		      (geu "geu") (leu "leu") ])
408(define_code_attr rCC [(ne "eq") (eq "ne") (lt "ge") (ltu "geu")
409		       (gt "le") (gtu "leu") (ge "lt") (le "gt")
410		       (geu "ltu") (leu "gtu") ])
411
412(define_insn "*b<cond:code>"
413  [(set (pc)
414	(if_then_else (cond (reg:CC CC_REG)
415			    (const_int 0))
416		      (label_ref (match_operand 0 "" ""))
417		      (pc)))]
418  ""
419{
420  if (get_attr_length (insn) == 2)
421    return "b<CC>\\t%l0";
422  else
423    return "b<rCC>\\t.+6\n\tjmpa   %l0";
424}
425  [(set (attr "length")
426        (if_then_else (lt (abs (minus (pc) (match_dup 0))) (const_int 1022))
427                      (const_int 2) (const_int 8)))])
428
429;; -------------------------------------------------------------------------
430;; Call and Jump instructions
431;; -------------------------------------------------------------------------
432
433(define_expand "call"
434  [(call (match_operand:QI 0 "memory_operand" "")
435		(match_operand 1 "general_operand" ""))]
436  ""
437{
438  gcc_assert (MEM_P (operands[0]));
439})
440
441(define_insn "*call"
442  [(call (mem:QI (match_operand:SI
443		  0 "nonmemory_operand" "i,r"))
444	 (match_operand 1 "" ""))]
445  ""
446  "@
447   jsra\\t%0
448   jsr\\t%0"
449  [(set_attr "length"	"6,2")])
450
451(define_expand "call_value"
452  [(set (match_operand 0 "" "")
453		(call (match_operand:QI 1 "memory_operand" "")
454		 (match_operand 2 "" "")))]
455  ""
456{
457  gcc_assert (MEM_P (operands[1]));
458})
459
460(define_insn "*call_value"
461  [(set (match_operand 0 "register_operand" "=r")
462	(call (mem:QI (match_operand:SI
463		       1 "immediate_operand" "i"))
464	      (match_operand 2 "" "")))]
465  ""
466  "jsra\\t%1"
467  [(set_attr "length"	"6")])
468
469(define_insn "*call_value_indirect"
470  [(set (match_operand 0 "register_operand" "=r")
471	(call (mem:QI (match_operand:SI
472		       1 "register_operand" "r"))
473	      (match_operand 2 "" "")))]
474  ""
475  "jsr\\t%1")
476
477(define_insn "indirect_jump"
478  [(set (pc) (match_operand:SI 0 "nonimmediate_operand" "r"))]
479  ""
480  "jmp\\t%0")
481
482(define_insn "jump"
483  [(set (pc)
484	(label_ref (match_operand 0 "" "")))]
485  ""
486  "jmpa\\t%l0"
487  [(set_attr "length"	"6")])
488
489
490;; -------------------------------------------------------------------------
491;; Prologue & Epilogue
492;; -------------------------------------------------------------------------
493
494(define_expand "prologue"
495  [(clobber (const_int 0))]
496  ""
497  "
498{
499  moxie_expand_prologue ();
500  DONE;
501}
502")
503
504(define_expand "epilogue"
505  [(return)]
506  ""
507  "
508{
509  moxie_expand_epilogue ();
510  DONE;
511}
512")
513
514(define_insn "returner"
515  [(return)]
516  "reload_completed"
517  "ret")
518