blob: e7172d3be61db98a4e054ef0242da3e9f70cf10a [file] [log] [blame]
PulkoMandy17fc7592022-07-28 18:27:54 +02001/*
2 * vscppc
3 *
4 * vbcc PowerPC scheduler
5 * (C)1998-2001 by Frank Wille <frank@phoenix.owl.de>
6 *
7 * vscppc is freeware and part of the portable and retargetable ANSI C
8 * compiler vbcc, copyright (c) 1995-98 by Volker Barthelmann.
9 * vscppc may be freely redistributed as long as no modifications are
10 * made and nothing is charged for it. Non-commercial usage is allowed
11 * without any restrictions.
12 * EVERY PRODUCT OR PROGRAM DERIVED DIRECTLY FROM MY SOURCE MAY NOT BE
13 * SOLD COMMERCIALLY WITHOUT PERMISSION FROM THE AUTHOR.
14 *
15 * History:
16 * V0.5 14-Feb-01
17 * FSCPR is no longer marked as used/modified, which allows the
18 * scheduler to rearrange all FPU instructions. As a consequence, the
19 * only instruction reading FPSCR, mffs, has to be marked as barrier.
20 * V0.4 01-Dec-99
21 * 603e PID7 seems to have a latency of 20 instead 37 for
22 * the "div" instruction (source: Michal Bartczak).
23 * V0.3b 30-Jul-98
24 * crxxx instructions used/modified wrong CCRs.
25 * V0.3a 21-Jul-98
26 * "la" instruction was not recognized.
27 * V0.3 20-Jul-98
28 * Target-specific options via sched_option() removed. Options
29 * are passed in the assembler source, e.g. "#vsc elf".
30 * Differentiation between 603 and 604 (selected by "#vsc cpu").
31 * Now, scheduling takes place with regard to the real PowerPC
32 * architecture.
33 * V0.2 12-Jul-98
34
35 * Option "-elf" lets the scheduler accept ELF/SVR4 sources,
36 * which only use numbers instead of full register names.
37 * Target-specific options require a modification in the
38 * portable scheduler part vsc.c.
39 * V0.1 10-Jul-98
40 * vscppc seems to be stable, after some tests.
41 * However, it still needs a lot of fine tuning (my PowerPC
42 * docs are at home).
43 * A differentiation between the PPC CPUs (603e, 604e) is missing.
44 * V0.0 09-Jul-98
45 * File created.
46 *
47 */
48
49#include "vsc.h"
50
51char tg_copyright[]="PowerPC scheduler V0.5 (c) in 1998-2001 by Frank Wille";
52
53static int elf=0,cpu=604;
54
55
56
57int sched_init(void)
58{
59 return (1);
60}
61
62
63void sched_cleanup(void)
64{
65}
66
67
68static void sched_option(char *s)
69{
70 if (!strncmp(s,"elf",3)) {
71 elf = 1;
72 }
73 else if (!strncmp(s,"cpu ",4)) {
74 if (!strncmp(s+4,"603",3))
75 cpu = 603;
76 else if (!strncmp(s+4,"604",3))
77 cpu = 604;
78 }
79}
80
81
82static char *strest(char *s,int n)
83/* returns ptr to the last n characters of string s */
84{
85 return (s + strlen(s) - n);
86}
87
88
89static int setlab(struct sinfo *p,char *lab)
90/* check for a valid local label */
91{
92 int i;
93
94 if (sscanf(lab,elf?".l%d":"l%d",&i) == 1) {
95 p->label = i;
96 return (1);
97 }
98 return (0);
99}
100
101
102static int lsreg(char *s)
103/* checks the operand for load/store addressing mode and returns */
104/* the base register on success, -1 otherwise */
105{
106 char *p = (s+strlen(s))-1;
107 int q;
108
109 while (p>s && *p!='(')
110 --p;
111 if (sscanf(p,elf?"(%d)":"(r%d)",&q) == 1)
112 return (q);
113 return (-1);
114}
115
116
117int sched_info(struct sinfo *p)
118{
119 char buf[16],oper[40],c;
120 int q1,q2,q3,z,i,x,n;
121
122 /* check for vscppc specific options in the source */
123 if (!strncmp(p->txt,"#vsc ",5)) {
124 sched_option(p->txt+5);
125 p->flags = BARRIER;
126 return (1);
127 }
128
129 if (!strncmp(p->txt,"#barrier",8)) {
130 /* an artificial barrier, used e.g. for inline-code */
131 p->flags = BARRIER;
132 return (1);
133 }
134
135 if (sscanf(p->txt," .%15s %39s",buf,oper) >= 1) {
136 /* assembler directive or macro */
137 p->flags = BARRIER;
138 return (1);
139 }
140
141 if (sscanf(p->txt,elf?".l%d:":"l%d:",&i) == 1) {
142 /* a local label */
143 p->label = i;
144 p->flags = LABEL;
145 return (1);
146 }
147
148 if (sscanf(p->txt," mffs%15s %39s",buf,oper) >= 1) {
149 /* mffs reads FPSCR and therefore has to be treated as a barrier, */
150 /* because FPSCR is never marked as used by the scheduler */
151 p->flags = BARRIER;
152 return (1);
153 }
154
155 if ((n = sscanf(p->txt," b%15s %39s",buf,oper)) >= 1) {
156 /* branch instruction */
157 p->latency = 1;
158 BSET(p->pipes,BPU);
159
160 if (n == 1) {
161 /* branch unconditional: b label */
162 if (setlab(p,buf)) {
163 p->flags = UNCOND_BRANCH;
164 return (1);
165 }
166 }
167 else {
168 char *a = strest(buf,3);
169
170 /* reject branch instructions ending with */
171 /* "lr", "ctr", "a" or "l", but accept "bnl" */
172 if ((strncmp(a+1,"lr",2) && strncmp(a,"ctr",3) &&
173 *(a+2)!='l' && *(a+2)!='a') ||
174 !strcmp(buf,"nl")) {
175
176 if (*buf == 'd') {
177 /* bdz... or bdnz... */
178 a = oper;
179 if (strcmp(buf,"dz") && strcmp(buf,"dnz")) {
180 while (*a && *a!=',')
181 a++;
182 if (*a == ',')
183 a++;
184 else
185 a = 0;
186 }
187 if (a) {
188 if (setlab(p,a)) {
189 p->flags = COND_BRANCH;
190 BSET(p->modifies,CTR);
191 /* @@@ unable to determine the used CCRs - set all to used */
192 for (x=CCR; x<(CCR+8); x++)
193 BSET(p->uses,x);
194 return (1);
195 }
196 }
197 }
198
199 else if (*buf == 'c') {
200 if (sscanf(oper,"%d,%d,%s",&q1,&q2,buf) == 3) {
201 /* conditional branch: bc m,n,label */
202 if (setlab(p,buf)) {
203 p->flags = COND_BRANCH;
204 BSET(p->uses,CCR+(q2>>2));
205 return (1);
206 }
207 }
208 }
209
210 else {
211 /* normal conditional branch: b<cond> [crN,]label */
212 a = buf;
213 if (sscanf(oper,elf?"%d,%s":"cr%d,%s",&i,buf) != 2) {
214 i = 0;
215 a = oper;
216 }
217 if (setlab(p,a)) {
218 p->flags = COND_BRANCH;
219 BSET(p->uses,CCR+i);
220 return (1);
221 }
222 }
223 }
224 }
225
226 p->flags = BARRIER;
227 return (1);
228 }
229
230
231 if (cpu == 603) {
232 /* scheduling for the PowerPC 603 */
233
234 if ((!elf && sscanf(p->txt," %15s %c%d,%39s",buf,&c,&z,oper) == 4) ||
235 (elf && sscanf(p->txt," %15s %d,%39s",buf,&z,oper) == 3)) {
236 if (elf) {
237 if ((buf[0]=='l' && buf[1]=='f') || (buf[0]=='s' && buf[2]=='f'))
238 c = 'f';
239 else
240 c = 'r';
241 }
242 if ((q1 = lsreg(oper))>=0 && (c=='r'||c=='f')) {
243 /* load/store instruction ...,d(rQ1) */
244
245 if (!strcmp(buf,"la")) {
246 /* la rZ,d(rQ1) is the same as: addi rZ,rQ1,d */
247 p->latency = 1;
248 BSET(p->pipes,IU);
249 BSET(p->pipes,SRU); /* addi may also execute in SRU */
250 BSET(p->uses,GPR+q1);
251 BSET(p->modifies,GPR+z);
252 return (1);
253 }
254
255 BSET(p->pipes,LSU);
256 if (*(strest(buf,1)) == 'u') /* update instruction? */
257 BSET(p->modifies,GPR+q1);
258 else
259 BSET(p->uses,GPR+q1);
260
261 if (c == 'r') {
262 /* integer load/store */
263
264 if (!strncmp(strest(buf,2),"mw",2)) {
265 /* load/store multiple word rz,i(rq1) */
266
267 if (*buf == 'l') {
268 p->latency = 2+(32-z);
269 for (x=z; x<32; x++)
270 BSET(p->modifies,GPR+x);
271 BSET(p->uses,MEM);
272 }
273 else {
274 p->latency = 1+(32-z);
275 for (x=z; x<32; x++)
276 BSET(p->uses,GPR+x);
277 BSET(p->modifies,MEM);
278 }
279 }
280 else {
281 /* load/store integer rz,i(rq1) */
282
283 p->latency = 3;
284 if(*buf == 'l') {
285 BSET(p->modifies,GPR+z);
286 BSET(p->uses,MEM);
287 }
288 else{
289 BSET(p->uses,GPR+z);
290 BSET(p->modifies,MEM);
291 }
292 }
293 }
294
295 else {
296 /* load/store float fz,d(rQ1) */
297
298 p->latency = 3;
299 if(*buf == 'l') {
300 BSET(p->modifies,FPR+z);
301 BSET(p->uses,MEM);
302 }
303 else{
304 BSET(p->uses,FPR+z);
305 BSET(p->modifies,MEM);
306 }
307 }
308
309 return (1);
310 }
311 }
312
313 if ((!elf && sscanf(p->txt," %15s %c%d,r%d,r%d",buf,&c,&z,&q1,&q2) == 5) ||
314 (elf && sscanf(p->txt," %15s %d,%d,%d",buf,&z,&q1,&q2) == 4)) {
315 if (*buf=='l' || (buf[0]=='s' && buf[1]=='t')) {
316 if (elf) {
317 if ((buf[0]=='l' && buf[1]=='f') || (buf[0]=='s' && buf[2]=='f'))
318 c = 'f';
319 else
320 c = 'r';
321 }
322
323 BSET(p->pipes,LSU);
324 BSET(p->uses,GPR+q2);
325 if (!strncmp(strest(buf,2),"ux",2)) /* update instruction? */
326 BSET(p->modifies,GPR+q1);
327 else
328 BSET(p->uses,GPR+q1);
329
330 if (c == 'r') {
331 /* integer load/store */
332
333 if (!strncmp(buf,"lsw",3) || !strncmp(buf,"stsw",4)) {
334 /* load/store string word rz,rq1,rq2/imm */
335 p->flags = BARRIER; /* too complex... ;) */
336 return (1);
337 }
338 else {
339 /* load/store integer indexed rz,rq1,rq2 */
340
341 p->latency = 3;
342 if(*buf == 'l') {
343 BSET(p->modifies,GPR+z);
344 BSET(p->uses,MEM);
345 }
346 else{
347 if (!strcmp(buf,"stwcx."))
348 p->latency = 8;
349 BSET(p->uses,GPR+z);
350 BSET(p->modifies,MEM);
351 }
352 return (1);
353 }
354 }
355
356 else if (c == 'f') {
357 /* load/store float indexed fz,rq1,rq2 */
358 p->latency = 3;
359 if(*buf == 'l') {
360 BSET(p->modifies,FPR+z);
361 BSET(p->uses,MEM);
362 }
363 else{
364 BSET(p->uses,FPR+z);
365 BSET(p->modifies,MEM);
366 }
367 return (1);
368 }
369 }
370 }
371
372 if (sscanf(p->txt,elf ? " fcm%15s %d,%d,%d" : " fcm%15s cr%d,f%d,f%d",
373 buf,&z,&q1,&q2) == 4) {
374 /* floating point compare CR0 */
375 p->latency = 3;
376 BSET(p->pipes,FPU);
377 BSET(p->modifies,CCR+z);
378 /*BSET(p->modifies,FPSCR);*/
379 BSET(p->uses,FPR+q1);
380 BSET(p->uses,FPR+q2);
381 return (1);
382 }
383 if (sscanf(p->txt,elf ? " fcm%15s %d,%d" : " fcm%15s f%d,f%d",
384 buf,&q1,&q2) == 3) {
385 /* floating point compare */
386 p->latency = 3;
387 BSET(p->pipes,FPU);
388 BSET(p->modifies,CCR);
389 /*BSET(p->modifies,FPSCR);*/
390 BSET(p->uses,FPR+q1);
391 BSET(p->uses,FPR+q2);
392 return (1);
393 }
394
395 if ((n = sscanf(p->txt,elf ? " f%15s %d,%d,%d,%d" :
396 " f%15s f%d,f%d,f%d,f%d",buf,&z,&q1,&q2,&q3))>=3) {
397 /* floating point operation with 2, 3 or 4 operands */
398
399#if 0
400 if (strncmp(buf,"abs",3) &&
401 strncmp(buf,"mr",2) &&
402 strncmp(buf,"nabs",4) &&
403 strncmp(buf,"neg",3) &&
404 strncmp(buf,"sel",3))
405 BSET(p->modifies,FPSCR); /* only some instr. don't alter FPSCR */
406#endif
407
408 if (!strncmp(buf,"divs",4) ||
409 !strncmp(buf,"res",3))
410 p->latency = 18;
411 else if (!strncmp(buf,"div",3))
412 p->latency = 33;
413 else if (!strncmp(buf,"mul",3) ||
414 !strncmp(buf,"madd",4) ||
415 !strncmp(buf,"msub",4) ||
416 !strncmp(buf,"nmadd",5) ||
417 !strncmp(buf,"nmsub",5))
418 p->latency = 4;
419 else
420 p->latency = 3;
421
422 if (*(strest(buf,1)) == '.')
423 BSET(p->modifies,CCR+1);
424 BSET(p->pipes,FPU);
425 BSET(p->uses,FPR+q1);
426 if (n >= 4) {
427 BSET(p->uses,FPR+q2);
428 if (n == 5)
429 BSET(p->uses,FPR+q3);
430 }
431 BSET(p->modifies,FPR+z);
432 return (1);
433 }
434
435 if (sscanf(p->txt,elf ? " cm%15s %d,%d,%d" : " cm%15s cr%d,r%d,r%d",
436 buf,&z,&q1,&q2) == 4) {
437 /* integer compare instruction */
438 p->latency = 1;
439 BSET(p->pipes,IU);
440 BSET(p->pipes,SRU);
441 BSET(p->modifies,CCR+z);
442 BSET(p->uses,GPR+q1);
443 if (*(strest(buf,1)) != 'i')
444 BSET(p->uses,GPR+q2);
445 return (1);
446 }
447 if (sscanf(p->txt,elf ? " cm%15s %d,%d" : " cm%15s r%d,r%d",
448 buf,&q1,&q2) == 3) {
449 /* integer compare instruction CR0 */
450 p->latency = 1;
451 BSET(p->pipes,IU);
452 BSET(p->pipes,SRU);
453 BSET(p->modifies,CCR);
454 BSET(p->uses,GPR+q1);
455 if (*(strest(buf,1)) != 'i')
456 BSET(p->uses,GPR+q2);
457 return (1);
458 }
459
460 if (!elf) {
461 if (sscanf(p->txt," cm%15s cr%d,r%d,%d",buf,&z,&q1,&i) == 4) {
462 /* immediate integer compare instruction */
463 p->latency = 1;
464 BSET(p->pipes,IU);
465 BSET(p->pipes,SRU);
466 BSET(p->modifies,CCR+z);
467 BSET(p->uses,GPR+q1);
468 return (1);
469 }
470 if (sscanf(p->txt," cm%15s r%d,%d",buf,&q1,&i) == 3) {
471 /* immediate integer compare instruction CR0 */
472 p->latency = 1;
473 BSET(p->pipes,IU);
474 BSET(p->pipes,SRU);
475 BSET(p->modifies,CCR+z);
476 BSET(p->uses,GPR+q1);
477 return (1);
478 }
479 }
480
481 if ((n = sscanf(p->txt," cr%15s %d,%d,%d",buf,&z,&q1,&q2)) >= 2) {
482 /* condition code register operation (vbcc uses this version) */
483 p->latency = 1;
484 BSET(p->pipes,SRU);
485 BSET(p->modifies,CCR+(z>>4));
486 if (n >= 3) {
487 BSET(p->uses,CCR+(q1>>4));
488 if (n == 4)
489 BSET(p->uses,CCR+(q2>>4));
490 }
491 return (1);
492 }
493
494 if (sscanf(p->txt,elf ? " rlw%15s %d,%d,%d,%d,%d" :
495 " rlw%15s r%d,r%d,%d,%d,%d",buf,&z,&q1,&i,&n,&x) == 6) {
496 /* rotate left: rlwimi, rlwinm, rlwnm r1,r2,x,y,z */
497 p->latency = 1;
498 BSET(p->pipes,IU);
499 if (*(strest(buf,1)) == '.')
500 BSET(p->modifies,CCR);
501 BSET(p->uses,GPR+q1);
502 BSET(p->modifies,GPR+z);
503 return (1);
504 }
505
506 if (sscanf(p->txt,elf ? " %15s %d,%d,%c" : " %15s r%d,r%d,%c",
507 buf,&z,&q1,&c) == 4) {
508 /* op r1,r2,imm */
509 if (!strncmp(buf,"addi",4) ||
510 !strncmp(buf,"andi",4) ||
511 !strncmp(buf,"mulli",5) ||
512 !strncmp(buf,"ori",3) ||
513 !strncmp(buf,"slwi",4) ||
514 !strncmp(buf,"srwi",4) ||
515 !strncmp(buf,"srawi",5) ||
516 !strncmp(buf,"subi",4) ||
517 !strncmp(buf,"xori",4)) {
518 char *a = strest(buf,1);
519
520 if (*buf == 'm') /* mulli */
521 p->latency = 3;
522 else
523 p->latency = 1;
524 BSET(p->pipes,IU);
525 if (!strncmp(buf,"add",3) && *(buf+4)!='c')
526 BSET(p->pipes,SRU); /* addi/addis may also execute in SRU */
527 if (*a == '.') {
528 BSET(p->modifies,CCR);
529 --a;
530 }
531 if (*a == 'c')
532 BSET(p->modifies,XER);
533 BSET(p->uses,GPR+q1);
534 BSET(p->modifies,GPR+z);
535 return (1);
536 }
537 }
538
539 if (sscanf(p->txt,elf ? " %15s %d,0,%d" : " %15s r%d,0,r%d",
540 buf,&z,&q2) == 3) {
541 /* op r1,0,r3 */
542 if (!strncmp(buf,"add",3) ||
543 !strncmp(buf,"sub",3)) {
544 p->latency = 1;
545 BSET(p->pipes,IU);
546 if (*(strest(buf,1)) == '.')
547 BSET(p->modifies,CCR);
548 else
549 BSET(p->pipes,SRU); /* add/addo may also execute in SRU */
550 BSET(p->uses,GPR+q2);
551 BSET(p->modifies,GPR+z);
552 return (1);
553 }
554 }
555
556 if (sscanf(p->txt,elf ? " %15s %d,%d,%d" : " %15s r%d,r%d,r%d",
557 buf,&z,&q1,&q2) == 4) {
558 /* op r1,r2,r3 */
559 if (!strncmp(buf,"add",3) ||
560 !strncmp(buf,"and",3) ||
561 !strncmp(buf,"div",3) ||
562 !strncmp(buf,"eqv",3) ||
563 !strncmp(buf,"mul",3) ||
564 !strncmp(buf,"nand",4) ||
565 !strncmp(buf,"nor",3) ||
566 !strncmp(buf,"or",2) ||
567 !strncmp(buf,"sl",2) ||
568 !strncmp(buf,"sr",2) ||
569 !strncmp(buf,"sub",3) ||
570 !strncmp(buf,"xor",3)) {
571 char *a = strest(buf,1);
572
573 if (!strncmp(buf,"mul",3)) {
574 if (*(buf+5) == 'u')
575 p->latency = 6; /* mulhwu needs 6 cycles */
576 else
577 p->latency = 5;
578 if (*(buf+3) == 'l')
579 BSET(p->modifies,XER);
580 }
581 else if (!strncmp(buf,"div",3)) {
582/* p->latency = 37;*/
583 p->latency = 20; /* 603e has 20 since PID7 */
584 BSET(p->modifies,XER);
585 }
586 else
587 p->latency = 1;
588 BSET(p->pipes,IU);
589 if (!strcmp(buf,"add") || !strcmp(buf,"addo"))
590 BSET(p->pipes,SRU); /* add/addo may also execute in SRU */
591
592 if (*a == '.') {
593 BSET(p->modifies,CCR);
594 --a;
595 }
596 if (*a == 'o') {
597 BSET(p->modifies,XER);
598 --a;
599 }
600 if (*a == 'c') {
601 BSET(p->modifies,XER);
602 --a;
603 }
604 if (*a == 'e')
605 BSET(p->uses,XER);
606 BSET(p->uses,GPR+q1);
607 BSET(p->uses,GPR+q2);
608 BSET(p->modifies,GPR+z);
609 return (1);
610 }
611 }
612
613 if (sscanf(p->txt,elf ? " l%15s %d,%c" : " l%15s r%d,%c",
614 buf,&z,&c) == 3) {
615 if (*buf == 'i') {
616 /* li, lis -> addi, addis */
617 p->latency = 1;
618 BSET(p->pipes,IU);
619 BSET(p->pipes,SRU);
620 BSET(p->modifies,GPR+z);
621 return (1);
622 }
623 }
624
625 if (sscanf(p->txt,elf ? " %15s %d,%d" : " %15s r%d,r%d",
626 buf,&z,&q1) == 3) {
627 /* op r1,r2 */
628 if (!strncmp(buf,"add",3) ||
629 !strncmp(buf,"exts",4) ||
630 !strncmp(buf,"mr",2) ||
631 !strncmp(buf,"neg",3) ||
632 !strncmp(buf,"sub",3)) {
633 char *a = strest(buf,1);
634
635 p->latency = 1;
636 if (*buf=='a' || *buf=='s')
637 BSET(p->uses,XER); /* addme/addze/subfme/subfze/... */
638 BSET(p->pipes,IU);
639 if (*a == '.') {
640 BSET(p->modifies,CCR);
641 --a;
642 }
643 if (*a == 'o') {
644 BSET(p->modifies,XER);
645 }
646 BSET(p->uses,GPR+q1);
647 BSET(p->modifies,GPR+z);
648 return (1);
649 }
650 }
651
652 if (sscanf(p->txt,elf?" m%15s %d":" m%15s r%d",buf,&z) == 2) {
653 /* mtxxx, mfxxx: move from/to special registers */
654 int reg=0;
655
656 if (!strcmp(&buf[1],"xer"))
657 reg = XER;
658 else if (!strcmp(&buf[1],"ctr"))
659 reg = CTR;
660 else if (!strcmp(&buf[1],"lr"))
661 reg = LR;
662 else if (!strncmp(&buf[1],"fs",2))
663 reg = FPSCR;
664 if (reg) {
665 if (reg == FPSCR) {
666 p->latency = 3;
667 BSET(p->pipes,FPU);
668 /*if (*buf == 'f') {
669 BSET(p->uses,reg);
670 BSET(p->modifies,z);
671 }
672 else {*/
673 BSET(p->uses,z);
674 BSET(p->modifies,reg);
675 /*}*/
676 }
677 else {
678 BSET(p->pipes,SRU);
679 if (*buf == 'f') {
680 p->latency = 1;
681 BSET(p->uses,reg);
682 BSET(p->modifies,z);
683 }
684 else {
685 p->latency = 2;
686 BSET(p->uses,z);
687 BSET(p->modifies,reg);
688 }
689 }
690 return (1);
691 }
692 }
693 }
694
695
696 else if (cpu == 604) {
697 /* scheduling for the PowerPC 604 */
698
699 if ((!elf && sscanf(p->txt," %15s %c%d,%39s",buf,&c,&z,oper) == 4) ||
700 (elf && sscanf(p->txt," %15s %d,%39s",buf,&z,oper) == 3)) {
701 if (elf) {
702 if ((buf[0]=='l' && buf[1]=='f') || (buf[0]=='s' && buf[2]=='f'))
703 c = 'f';
704 else
705 c = 'r';
706 }
707 if ((q1 = lsreg(oper))>=0 && (c=='r'||c=='f')) {
708 /* load/store instruction ...,d(rQ1) */
709
710 if (!strcmp(buf,"la")) {
711 /* la rZ,d(rQ1) is the same as: addi rZ,rQ1,d */
712 p->latency = 1;
713 BSET(p->pipes,SCIU1);
714 BSET(p->pipes,SCIU2);
715 BSET(p->uses,GPR+q1);
716 BSET(p->modifies,GPR+z);
717 return (1);
718 }
719
720 BSET(p->pipes,LSU);
721 if (*(strest(buf,1)) == 'u') /* update instruction? */
722 BSET(p->modifies,GPR+q1);
723 else
724 BSET(p->uses,GPR+q1);
725
726 if (c == 'r') {
727 /* integer load/store */
728
729 if (!strncmp(strest(buf,2),"mw",2)) {
730 /* load/store multiple word rz,i(rq1) */
731
732 p->latency = 2+(32-z);
733 if (*buf == 'l') {
734 for (x=z; x<32; x++)
735 BSET(p->modifies,GPR+x);
736 BSET(p->uses,MEM);
737 }
738 else {
739 for (x=z; x<32; x++)
740 BSET(p->uses,GPR+x);
741 BSET(p->modifies,MEM);
742 }
743 }
744 else {
745 /* load/store integer rz,i(rq1) */
746
747 if(*buf == 'l') {
748 p->latency = 2;
749 BSET(p->modifies,GPR+z);
750 BSET(p->uses,MEM);
751 }
752 else{
753 p->latency = 3;
754 BSET(p->uses,GPR+z);
755 BSET(p->modifies,MEM);
756 }
757 }
758 }
759
760 else {
761 /* load/store float fz,d(rQ1) */
762
763 p->latency = 3;
764 if(*buf == 'l') {
765 BSET(p->modifies,FPR+z);
766 BSET(p->uses,MEM);
767 }
768 else{
769 BSET(p->uses,FPR+z);
770 BSET(p->modifies,MEM);
771 }
772 }
773
774 return (1);
775 }
776 }
777
778 if ((!elf && sscanf(p->txt," %15s %c%d,r%d,r%d",buf,&c,&z,&q1,&q2) == 5) ||
779 (elf && sscanf(p->txt," %15s %d,%d,%d",buf,&z,&q1,&q2) == 4)) {
780 if (*buf=='l' || (buf[0]=='s' && buf[1]=='t')) {
781 if (elf) {
782 if ((buf[0]=='l' && buf[1]=='f') || (buf[0]=='s' && buf[2]=='f'))
783 c = 'f';
784 else
785 c = 'r';
786 }
787
788 BSET(p->pipes,LSU);
789 BSET(p->uses,GPR+q2);
790 if (!strncmp(strest(buf,2),"ux",2)) /* update instruction? */
791 BSET(p->modifies,GPR+q1);
792 else
793 BSET(p->uses,GPR+q1);
794
795 if (c == 'r') {
796 /* integer load/store */
797
798 if (!strncmp(buf,"lsw",3) || !strncmp(buf,"stsw",4)) {
799 /* load/store string word rz,rq1,rq2/imm */
800 p->flags = BARRIER; /* too complex... ;) */
801 return (1);
802 }
803 else {
804 /* load/store integer indexed rz,rq1,rq2 */
805
806 if(*buf == 'l') {
807 p->latency = 2;
808 BSET(p->modifies,GPR+z);
809 BSET(p->uses,MEM);
810 }
811 else{
812 p->latency = 3;
813 BSET(p->uses,GPR+z);
814 BSET(p->modifies,MEM);
815 }
816 return (1);
817 }
818 }
819
820 else if (c == 'f') {
821 /* load/store float indexed fz,rq1,rq2 */
822 p->latency = 3;
823 if(*buf == 'l') {
824 BSET(p->modifies,FPR+z);
825 BSET(p->uses,MEM);
826 }
827 else{
828 BSET(p->uses,FPR+z);
829 BSET(p->modifies,MEM);
830 }
831 return (1);
832 }
833 }
834 }
835
836 if (sscanf(p->txt,elf ? " fcm%15s %d,%d,%d" : " fcm%15s cr%d,f%d,f%d",
837 buf,&z,&q1,&q2) == 4) {
838 /* floating point compare CR0 */
839 p->latency = 3;
840 BSET(p->pipes,FPU);
841 BSET(p->modifies,CCR+z);
842 /*BSET(p->modifies,FPSCR);*/
843 BSET(p->uses,FPR+q1);
844 BSET(p->uses,FPR+q2);
845 return (1);
846 }
847 if (sscanf(p->txt,elf ? " fcm%15s %d,%d" : " fcm%15s f%d,f%d",
848 buf,&q1,&q2) == 3) {
849 /* floating point compare */
850 p->latency = 3;
851 BSET(p->pipes,FPU);
852 BSET(p->modifies,CCR);
853 /*BSET(p->modifies,FPSCR);*/
854 BSET(p->uses,FPR+q1);
855 BSET(p->uses,FPR+q2);
856 return (1);
857 }
858
859 if ((n = sscanf(p->txt,elf ? " f%15s %d,%d,%d,%d" :
860 " f%15s f%d,f%d,f%d,f%d",buf,&z,&q1,&q2,&q3))>=3) {
861 /* floating point operation with 2, 3 or 4 operands */
862
863#if 0
864 if (strncmp(buf,"abs",3) &&
865 strncmp(buf,"mr",2) &&
866 strncmp(buf,"nabs",4) &&
867 strncmp(buf,"neg",3) &&
868 strncmp(buf,"sel",3))
869 BSET(p->modifies,FPSCR); /* only some instr. don't alter FPSCR */
870#endif
871
872 if (!strncmp(buf,"divs",4) ||
873 !strncmp(buf,"res",3))
874 p->latency = 18;
875 else if (!strncmp(buf,"div",3))
876 p->latency = 32;
877 else
878 p->latency = 3;
879
880 if (*(strest(buf,1)) == '.')
881 BSET(p->modifies,CCR+1);
882 BSET(p->pipes,FPU);
883 BSET(p->uses,FPR+q1);
884 if (n >= 4) {
885 BSET(p->uses,FPR+q2);
886 if (n == 5)
887 BSET(p->uses,FPR+q3);
888 }
889 BSET(p->modifies,FPR+z);
890 return (1);
891 }
892
893 if (sscanf(p->txt,elf ? " cm%15s %d,%d,%d" : " cm%15s cr%d,r%d,r%d",
894 buf,&z,&q1,&q2) == 4) {
895 /* integer compare instruction */
896 p->latency = 1;
897 BSET(p->pipes,SCIU1);
898 BSET(p->pipes,SCIU2);
899 BSET(p->modifies,CCR+z);
900 BSET(p->uses,GPR+q1);
901 if (*(strest(buf,1)) != 'i')
902 BSET(p->uses,GPR+q2);
903 return (1);
904 }
905 if (sscanf(p->txt,elf ? " cm%15s %d,%d" : " cm%15s r%d,r%d",
906 buf,&q1,&q2) == 3) {
907 /* integer compare instruction CR0 */
908 p->latency = 1;
909 BSET(p->pipes,SCIU1);
910 BSET(p->pipes,SCIU2);
911 BSET(p->modifies,CCR);
912 BSET(p->uses,GPR+q1);
913 if (*(strest(buf,1)) != 'i')
914 BSET(p->uses,GPR+q2);
915 return (1);
916 }
917
918 if (!elf) {
919 if (sscanf(p->txt," cm%15s cr%d,r%d,%d",buf,&z,&q1,&i) == 4) {
920 /* immediate integer compare instruction */
921 p->latency = 1;
922 BSET(p->pipes,SCIU1);
923 BSET(p->pipes,SCIU2);
924 BSET(p->modifies,CCR+z);
925 BSET(p->uses,GPR+q1);
926 return (1);
927 }
928 if (sscanf(p->txt," cm%15s r%d,%d",buf,&q1,&i) == 3) {
929 /* immediate integer compare instruction CR0 */
930 p->latency = 1;
931 BSET(p->pipes,SCIU1);
932 BSET(p->pipes,SCIU2);
933 BSET(p->modifies,CCR+z);
934 BSET(p->uses,GPR+q1);
935
936 return (1);
937 }
938 }
939
940 if ((n = sscanf(p->txt," cr%15s %d,%d,%d",buf,&z,&q1,&q2)) >= 2) {
941 /* condition code register operation (vbcc uses this version) */
942 p->latency = 1;
943 BSET(p->pipes,CRU);
944 BSET(p->modifies,CCR+(z>>4));
945 if (n >= 3) {
946 BSET(p->uses,CCR+(q1>>4));
947 if (n == 4)
948 BSET(p->uses,CCR+(q2>>4));
949 }
950 return (1);
951 }
952
953 if (sscanf(p->txt,elf ? " rlw%15s %d,%d,%d,%d,%d" :
954 " rlw%15s r%d,r%d,%d,%d,%d",buf,&z,&q1,&i,&n,&x) == 6) {
955 /* rotate left: rlwimi, rlwinm, rlwnm r1,r2,x,y,z */
956 p->latency = 1;
957 BSET(p->pipes,SCIU1);
958 BSET(p->pipes,SCIU2);
959 if (*(strest(buf,1)) == '.')
960 BSET(p->modifies,CCR);
961 BSET(p->uses,GPR+q1);
962 BSET(p->modifies,GPR+z);
963 return (1);
964 }
965
966 if (sscanf(p->txt,elf ? " %15s %d,%d,%c" : " %15s r%d,r%d,%c",
967 buf,&z,&q1,&c) == 4) {
968 /* op r1,r2,imm */
969 if (!strncmp(buf,"addi",4) ||
970 !strncmp(buf,"andi",4) ||
971 !strncmp(buf,"mulli",5) ||
972 !strncmp(buf,"ori",3) ||
973 !strncmp(buf,"slwi",4) ||
974 !strncmp(buf,"srwi",4) ||
975 !strncmp(buf,"srawi",5) ||
976 !strncmp(buf,"subi",4) ||
977 !strncmp(buf,"xori",4)) {
978 char *a = strest(buf,1);
979
980 if (*buf == 'm') { /* mulli */
981 p->latency = 3;
982 BSET(p->pipes,MCIU);
983 }
984 else {
985 p->latency = 1;
986 BSET(p->pipes,SCIU1);
987 BSET(p->pipes,SCIU2);
988 }
989 if (*a == '.') {
990 BSET(p->modifies,CCR);
991 --a;
992 }
993 if (*a == 'c')
994 BSET(p->modifies,XER);
995 BSET(p->uses,GPR+q1);
996 BSET(p->modifies,GPR+z);
997 return (1);
998 }
999 }
1000
1001 if (sscanf(p->txt,elf ? " %15s %d,0,%d" : " %15s r%d,0,r%d",
1002 buf,&z,&q2) == 3) {
1003 /* op r1,0,r3 */
1004 if (!strncmp(buf,"add",3) ||
1005 !strncmp(buf,"sub",3)) {
1006 p->latency = 1;
1007 BSET(p->pipes,SCIU1);
1008 BSET(p->pipes,SCIU2);
1009 if (*(strest(buf,1)) == '.')
1010 BSET(p->modifies,CCR);
1011 else
1012 BSET(p->pipes,SRU); /* add/addo may also execute in SRU */
1013 BSET(p->uses,GPR+q2);
1014 BSET(p->modifies,GPR+z);
1015 return (1);
1016 }
1017 }
1018
1019 if (sscanf(p->txt,elf ? " %15s %d,%d,%d" : " %15s r%d,r%d,r%d",
1020 buf,&z,&q1,&q2) == 4) {
1021 /* op r1,r2,r3 */
1022 if (!strncmp(buf,"add",3) ||
1023 !strncmp(buf,"and",3) ||
1024 !strncmp(buf,"div",3) ||
1025 !strncmp(buf,"eqv",3) ||
1026 !strncmp(buf,"mul",3) ||
1027 !strncmp(buf,"nand",4) ||
1028 !strncmp(buf,"nor",3) ||
1029 !strncmp(buf,"or",2) ||
1030 !strncmp(buf,"sl",2) ||
1031 !strncmp(buf,"sr",2) ||
1032 !strncmp(buf,"sub",3) ||
1033 !strncmp(buf,"xor",3)) {
1034 char *a = strest(buf,1);
1035
1036 if (!strncmp(buf,"mul",3)) {
1037 p->latency = 4;
1038 BSET(p->pipes,MCIU);
1039 if (*(buf+3) == 'l')
1040 BSET(p->modifies,XER);
1041 }
1042 else if (!strncmp(buf,"div",3)) {
1043 p->latency = 20;
1044 BSET(p->pipes,MCIU);
1045 BSET(p->modifies,XER);
1046 }
1047 else {
1048 p->latency = 1;
1049 BSET(p->pipes,SCIU1);
1050 BSET(p->pipes,SCIU2);
1051 }
1052 if (*a == '.') {
1053 BSET(p->modifies,CCR);
1054 --a;
1055 }
1056 if (*a == 'o') {
1057 BSET(p->modifies,XER);
1058 --a;
1059 }
1060 if (*a == 'c') {
1061 BSET(p->modifies,XER);
1062 --a;
1063 }
1064 if (*a == 'e')
1065 BSET(p->uses,XER);
1066 BSET(p->uses,GPR+q1);
1067 BSET(p->uses,GPR+q2);
1068 BSET(p->modifies,GPR+z);
1069 return (1);
1070 }
1071 }
1072
1073 if (sscanf(p->txt,elf ? " l%15s %d,%c" : " l%15s r%d,%c",
1074 buf,&z,&c) == 3) {
1075 if (*buf == 'i') {
1076 /* li, lis -> addi, addis */
1077 p->latency = 1;
1078 BSET(p->pipes,SCIU1);
1079 BSET(p->pipes,SCIU2);
1080 BSET(p->modifies,GPR+z);
1081 return (1);
1082 }
1083 }
1084
1085 if (sscanf(p->txt,elf ? " %15s %d,%d" : " %15s r%d,r%d",
1086 buf,&z,&q1) == 3) {
1087 /* op r1,r2 */
1088 if (!strncmp(buf,"add",3) ||
1089 !strncmp(buf,"exts",4) ||
1090 !strncmp(buf,"mr",2) ||
1091 !strncmp(buf,"neg",3) ||
1092 !strncmp(buf,"sub",3)) {
1093 char *a = strest(buf,1);
1094
1095 p->latency = 1;
1096 BSET(p->pipes,SCIU1);
1097 BSET(p->pipes,SCIU2);
1098 if (*buf=='a' || *buf=='s')
1099 BSET(p->uses,XER); /* addme/addze/subfme/subfze/... */
1100 if (*a == '.') {
1101 BSET(p->modifies,CCR);
1102 --a;
1103 }
1104 if (*a == 'o') {
1105 BSET(p->modifies,XER);
1106 }
1107 BSET(p->uses,GPR+q1);
1108 BSET(p->modifies,GPR+z);
1109 return (1);
1110 }
1111 }
1112
1113 if (sscanf(p->txt,elf?" m%15s %d":" m%15s r%d",buf,&z) == 2) {
1114 /* mtxxx, mfxxx: move from/to special registers */
1115 int reg=0;
1116
1117 if (!strcmp(&buf[1],"xer"))
1118 reg = XER;
1119 else if (!strcmp(&buf[1],"ctr"))
1120 reg = CTR;
1121 else if (!strcmp(&buf[1],"lr"))
1122 reg = LR;
1123 else if (!strncmp(&buf[1],"fs",2))
1124 reg = FPSCR;
1125 if (reg) {
1126 if (reg == FPSCR) {
1127 p->latency = 3;
1128 BSET(p->pipes,FPU);
1129 /*if (*buf == 'f') {
1130 BSET(p->uses,reg);
1131 BSET(p->modifies,z);
1132 }
1133 else {*/
1134 BSET(p->uses,z);
1135 BSET(p->modifies,reg);
1136 /*}*/
1137 }
1138 else {
1139 BSET(p->pipes,MCIU);
1140 if (*buf == 'f') {
1141 p->latency = 3;
1142 BSET(p->uses,reg);
1143 BSET(p->modifies,z);
1144 }
1145 else {
1146 p->latency = 1;
1147 BSET(p->uses,z);
1148 BSET(p->modifies,reg);
1149 }
1150 }
1151 return (1);
1152 }
1153 }
1154 }
1155
1156 p->flags = BARRIER;
1157 return (1);
1158}