| /* |
| * vscppc |
| * |
| * vbcc PowerPC scheduler |
| * (C)1998-2001 by Frank Wille <frank@phoenix.owl.de> |
| * |
| * vscppc is freeware and part of the portable and retargetable ANSI C |
| * compiler vbcc, copyright (c) 1995-98 by Volker Barthelmann. |
| * vscppc may be freely redistributed as long as no modifications are |
| * made and nothing is charged for it. Non-commercial usage is allowed |
| * without any restrictions. |
| * EVERY PRODUCT OR PROGRAM DERIVED DIRECTLY FROM MY SOURCE MAY NOT BE |
| * SOLD COMMERCIALLY WITHOUT PERMISSION FROM THE AUTHOR. |
| * |
| * History: |
| * V0.5 14-Feb-01 |
| * FSCPR is no longer marked as used/modified, which allows the |
| * scheduler to rearrange all FPU instructions. As a consequence, the |
| * only instruction reading FPSCR, mffs, has to be marked as barrier. |
| * V0.4 01-Dec-99 |
| * 603e PID7 seems to have a latency of 20 instead 37 for |
| * the "div" instruction (source: Michal Bartczak). |
| * V0.3b 30-Jul-98 |
| * crxxx instructions used/modified wrong CCRs. |
| * V0.3a 21-Jul-98 |
| * "la" instruction was not recognized. |
| * V0.3 20-Jul-98 |
| * Target-specific options via sched_option() removed. Options |
| * are passed in the assembler source, e.g. "#vsc elf". |
| * Differentiation between 603 and 604 (selected by "#vsc cpu"). |
| * Now, scheduling takes place with regard to the real PowerPC |
| * architecture. |
| * V0.2 12-Jul-98 |
| |
| * Option "-elf" lets the scheduler accept ELF/SVR4 sources, |
| * which only use numbers instead of full register names. |
| * Target-specific options require a modification in the |
| * portable scheduler part vsc.c. |
| * V0.1 10-Jul-98 |
| * vscppc seems to be stable, after some tests. |
| * However, it still needs a lot of fine tuning (my PowerPC |
| * docs are at home). |
| * A differentiation between the PPC CPUs (603e, 604e) is missing. |
| * V0.0 09-Jul-98 |
| * File created. |
| * |
| */ |
| |
| #include "vsc.h" |
| |
| char tg_copyright[]="PowerPC scheduler V0.5 (c) in 1998-2001 by Frank Wille"; |
| |
| static int elf=0,cpu=604; |
| |
| |
| |
| int sched_init(void) |
| { |
| return (1); |
| } |
| |
| |
| void sched_cleanup(void) |
| { |
| } |
| |
| |
| static void sched_option(char *s) |
| { |
| if (!strncmp(s,"elf",3)) { |
| elf = 1; |
| } |
| else if (!strncmp(s,"cpu ",4)) { |
| if (!strncmp(s+4,"603",3)) |
| cpu = 603; |
| else if (!strncmp(s+4,"604",3)) |
| cpu = 604; |
| } |
| } |
| |
| |
| static char *strest(char *s,int n) |
| /* returns ptr to the last n characters of string s */ |
| { |
| return (s + strlen(s) - n); |
| } |
| |
| |
| static int setlab(struct sinfo *p,char *lab) |
| /* check for a valid local label */ |
| { |
| int i; |
| |
| if (sscanf(lab,elf?".l%d":"l%d",&i) == 1) { |
| p->label = i; |
| return (1); |
| } |
| return (0); |
| } |
| |
| |
| static int lsreg(char *s) |
| /* checks the operand for load/store addressing mode and returns */ |
| /* the base register on success, -1 otherwise */ |
| { |
| char *p = (s+strlen(s))-1; |
| int q; |
| |
| while (p>s && *p!='(') |
| --p; |
| if (sscanf(p,elf?"(%d)":"(r%d)",&q) == 1) |
| return (q); |
| return (-1); |
| } |
| |
| |
| int sched_info(struct sinfo *p) |
| { |
| char buf[16],oper[40],c; |
| int q1,q2,q3,z,i,x,n; |
| |
| /* check for vscppc specific options in the source */ |
| if (!strncmp(p->txt,"#vsc ",5)) { |
| sched_option(p->txt+5); |
| p->flags = BARRIER; |
| return (1); |
| } |
| |
| if (!strncmp(p->txt,"#barrier",8)) { |
| /* an artificial barrier, used e.g. for inline-code */ |
| p->flags = BARRIER; |
| return (1); |
| } |
| |
| if (sscanf(p->txt," .%15s %39s",buf,oper) >= 1) { |
| /* assembler directive or macro */ |
| p->flags = BARRIER; |
| return (1); |
| } |
| |
| if (sscanf(p->txt,elf?".l%d:":"l%d:",&i) == 1) { |
| /* a local label */ |
| p->label = i; |
| p->flags = LABEL; |
| return (1); |
| } |
| |
| if (sscanf(p->txt," mffs%15s %39s",buf,oper) >= 1) { |
| /* mffs reads FPSCR and therefore has to be treated as a barrier, */ |
| /* because FPSCR is never marked as used by the scheduler */ |
| p->flags = BARRIER; |
| return (1); |
| } |
| |
| if ((n = sscanf(p->txt," b%15s %39s",buf,oper)) >= 1) { |
| /* branch instruction */ |
| p->latency = 1; |
| BSET(p->pipes,BPU); |
| |
| if (n == 1) { |
| /* branch unconditional: b label */ |
| if (setlab(p,buf)) { |
| p->flags = UNCOND_BRANCH; |
| return (1); |
| } |
| } |
| else { |
| char *a = strest(buf,3); |
| |
| /* reject branch instructions ending with */ |
| /* "lr", "ctr", "a" or "l", but accept "bnl" */ |
| if ((strncmp(a+1,"lr",2) && strncmp(a,"ctr",3) && |
| *(a+2)!='l' && *(a+2)!='a') || |
| !strcmp(buf,"nl")) { |
| |
| if (*buf == 'd') { |
| /* bdz... or bdnz... */ |
| a = oper; |
| if (strcmp(buf,"dz") && strcmp(buf,"dnz")) { |
| while (*a && *a!=',') |
| a++; |
| if (*a == ',') |
| a++; |
| else |
| a = 0; |
| } |
| if (a) { |
| if (setlab(p,a)) { |
| p->flags = COND_BRANCH; |
| BSET(p->modifies,CTR); |
| /* @@@ unable to determine the used CCRs - set all to used */ |
| for (x=CCR; x<(CCR+8); x++) |
| BSET(p->uses,x); |
| return (1); |
| } |
| } |
| } |
| |
| else if (*buf == 'c') { |
| if (sscanf(oper,"%d,%d,%s",&q1,&q2,buf) == 3) { |
| /* conditional branch: bc m,n,label */ |
| if (setlab(p,buf)) { |
| p->flags = COND_BRANCH; |
| BSET(p->uses,CCR+(q2>>2)); |
| return (1); |
| } |
| } |
| } |
| |
| else { |
| /* normal conditional branch: b<cond> [crN,]label */ |
| a = buf; |
| if (sscanf(oper,elf?"%d,%s":"cr%d,%s",&i,buf) != 2) { |
| i = 0; |
| a = oper; |
| } |
| if (setlab(p,a)) { |
| p->flags = COND_BRANCH; |
| BSET(p->uses,CCR+i); |
| return (1); |
| } |
| } |
| } |
| } |
| |
| p->flags = BARRIER; |
| return (1); |
| } |
| |
| |
| if (cpu == 603) { |
| /* scheduling for the PowerPC 603 */ |
| |
| if ((!elf && sscanf(p->txt," %15s %c%d,%39s",buf,&c,&z,oper) == 4) || |
| (elf && sscanf(p->txt," %15s %d,%39s",buf,&z,oper) == 3)) { |
| if (elf) { |
| if ((buf[0]=='l' && buf[1]=='f') || (buf[0]=='s' && buf[2]=='f')) |
| c = 'f'; |
| else |
| c = 'r'; |
| } |
| if ((q1 = lsreg(oper))>=0 && (c=='r'||c=='f')) { |
| /* load/store instruction ...,d(rQ1) */ |
| |
| if (!strcmp(buf,"la")) { |
| /* la rZ,d(rQ1) is the same as: addi rZ,rQ1,d */ |
| p->latency = 1; |
| BSET(p->pipes,IU); |
| BSET(p->pipes,SRU); /* addi may also execute in SRU */ |
| BSET(p->uses,GPR+q1); |
| BSET(p->modifies,GPR+z); |
| return (1); |
| } |
| |
| BSET(p->pipes,LSU); |
| if (*(strest(buf,1)) == 'u') /* update instruction? */ |
| BSET(p->modifies,GPR+q1); |
| else |
| BSET(p->uses,GPR+q1); |
| |
| if (c == 'r') { |
| /* integer load/store */ |
| |
| if (!strncmp(strest(buf,2),"mw",2)) { |
| /* load/store multiple word rz,i(rq1) */ |
| |
| if (*buf == 'l') { |
| p->latency = 2+(32-z); |
| for (x=z; x<32; x++) |
| BSET(p->modifies,GPR+x); |
| BSET(p->uses,MEM); |
| } |
| else { |
| p->latency = 1+(32-z); |
| for (x=z; x<32; x++) |
| BSET(p->uses,GPR+x); |
| BSET(p->modifies,MEM); |
| } |
| } |
| else { |
| /* load/store integer rz,i(rq1) */ |
| |
| p->latency = 3; |
| if(*buf == 'l') { |
| BSET(p->modifies,GPR+z); |
| BSET(p->uses,MEM); |
| } |
| else{ |
| BSET(p->uses,GPR+z); |
| BSET(p->modifies,MEM); |
| } |
| } |
| } |
| |
| else { |
| /* load/store float fz,d(rQ1) */ |
| |
| p->latency = 3; |
| if(*buf == 'l') { |
| BSET(p->modifies,FPR+z); |
| BSET(p->uses,MEM); |
| } |
| else{ |
| BSET(p->uses,FPR+z); |
| BSET(p->modifies,MEM); |
| } |
| } |
| |
| return (1); |
| } |
| } |
| |
| if ((!elf && sscanf(p->txt," %15s %c%d,r%d,r%d",buf,&c,&z,&q1,&q2) == 5) || |
| (elf && sscanf(p->txt," %15s %d,%d,%d",buf,&z,&q1,&q2) == 4)) { |
| if (*buf=='l' || (buf[0]=='s' && buf[1]=='t')) { |
| if (elf) { |
| if ((buf[0]=='l' && buf[1]=='f') || (buf[0]=='s' && buf[2]=='f')) |
| c = 'f'; |
| else |
| c = 'r'; |
| } |
| |
| BSET(p->pipes,LSU); |
| BSET(p->uses,GPR+q2); |
| if (!strncmp(strest(buf,2),"ux",2)) /* update instruction? */ |
| BSET(p->modifies,GPR+q1); |
| else |
| BSET(p->uses,GPR+q1); |
| |
| if (c == 'r') { |
| /* integer load/store */ |
| |
| if (!strncmp(buf,"lsw",3) || !strncmp(buf,"stsw",4)) { |
| /* load/store string word rz,rq1,rq2/imm */ |
| p->flags = BARRIER; /* too complex... ;) */ |
| return (1); |
| } |
| else { |
| /* load/store integer indexed rz,rq1,rq2 */ |
| |
| p->latency = 3; |
| if(*buf == 'l') { |
| BSET(p->modifies,GPR+z); |
| BSET(p->uses,MEM); |
| } |
| else{ |
| if (!strcmp(buf,"stwcx.")) |
| p->latency = 8; |
| BSET(p->uses,GPR+z); |
| BSET(p->modifies,MEM); |
| } |
| return (1); |
| } |
| } |
| |
| else if (c == 'f') { |
| /* load/store float indexed fz,rq1,rq2 */ |
| p->latency = 3; |
| if(*buf == 'l') { |
| BSET(p->modifies,FPR+z); |
| BSET(p->uses,MEM); |
| } |
| else{ |
| BSET(p->uses,FPR+z); |
| BSET(p->modifies,MEM); |
| } |
| return (1); |
| } |
| } |
| } |
| |
| if (sscanf(p->txt,elf ? " fcm%15s %d,%d,%d" : " fcm%15s cr%d,f%d,f%d", |
| buf,&z,&q1,&q2) == 4) { |
| /* floating point compare CR0 */ |
| p->latency = 3; |
| BSET(p->pipes,FPU); |
| BSET(p->modifies,CCR+z); |
| /*BSET(p->modifies,FPSCR);*/ |
| BSET(p->uses,FPR+q1); |
| BSET(p->uses,FPR+q2); |
| return (1); |
| } |
| if (sscanf(p->txt,elf ? " fcm%15s %d,%d" : " fcm%15s f%d,f%d", |
| buf,&q1,&q2) == 3) { |
| /* floating point compare */ |
| p->latency = 3; |
| BSET(p->pipes,FPU); |
| BSET(p->modifies,CCR); |
| /*BSET(p->modifies,FPSCR);*/ |
| BSET(p->uses,FPR+q1); |
| BSET(p->uses,FPR+q2); |
| return (1); |
| } |
| |
| if ((n = sscanf(p->txt,elf ? " f%15s %d,%d,%d,%d" : |
| " f%15s f%d,f%d,f%d,f%d",buf,&z,&q1,&q2,&q3))>=3) { |
| /* floating point operation with 2, 3 or 4 operands */ |
| |
| #if 0 |
| if (strncmp(buf,"abs",3) && |
| strncmp(buf,"mr",2) && |
| strncmp(buf,"nabs",4) && |
| strncmp(buf,"neg",3) && |
| strncmp(buf,"sel",3)) |
| BSET(p->modifies,FPSCR); /* only some instr. don't alter FPSCR */ |
| #endif |
| |
| if (!strncmp(buf,"divs",4) || |
| !strncmp(buf,"res",3)) |
| p->latency = 18; |
| else if (!strncmp(buf,"div",3)) |
| p->latency = 33; |
| else if (!strncmp(buf,"mul",3) || |
| !strncmp(buf,"madd",4) || |
| !strncmp(buf,"msub",4) || |
| !strncmp(buf,"nmadd",5) || |
| !strncmp(buf,"nmsub",5)) |
| p->latency = 4; |
| else |
| p->latency = 3; |
| |
| if (*(strest(buf,1)) == '.') |
| BSET(p->modifies,CCR+1); |
| BSET(p->pipes,FPU); |
| BSET(p->uses,FPR+q1); |
| if (n >= 4) { |
| BSET(p->uses,FPR+q2); |
| if (n == 5) |
| BSET(p->uses,FPR+q3); |
| } |
| BSET(p->modifies,FPR+z); |
| return (1); |
| } |
| |
| if (sscanf(p->txt,elf ? " cm%15s %d,%d,%d" : " cm%15s cr%d,r%d,r%d", |
| buf,&z,&q1,&q2) == 4) { |
| /* integer compare instruction */ |
| p->latency = 1; |
| BSET(p->pipes,IU); |
| BSET(p->pipes,SRU); |
| BSET(p->modifies,CCR+z); |
| BSET(p->uses,GPR+q1); |
| if (*(strest(buf,1)) != 'i') |
| BSET(p->uses,GPR+q2); |
| return (1); |
| } |
| if (sscanf(p->txt,elf ? " cm%15s %d,%d" : " cm%15s r%d,r%d", |
| buf,&q1,&q2) == 3) { |
| /* integer compare instruction CR0 */ |
| p->latency = 1; |
| BSET(p->pipes,IU); |
| BSET(p->pipes,SRU); |
| BSET(p->modifies,CCR); |
| BSET(p->uses,GPR+q1); |
| if (*(strest(buf,1)) != 'i') |
| BSET(p->uses,GPR+q2); |
| return (1); |
| } |
| |
| if (!elf) { |
| if (sscanf(p->txt," cm%15s cr%d,r%d,%d",buf,&z,&q1,&i) == 4) { |
| /* immediate integer compare instruction */ |
| p->latency = 1; |
| BSET(p->pipes,IU); |
| BSET(p->pipes,SRU); |
| BSET(p->modifies,CCR+z); |
| BSET(p->uses,GPR+q1); |
| return (1); |
| } |
| if (sscanf(p->txt," cm%15s r%d,%d",buf,&q1,&i) == 3) { |
| /* immediate integer compare instruction CR0 */ |
| p->latency = 1; |
| BSET(p->pipes,IU); |
| BSET(p->pipes,SRU); |
| BSET(p->modifies,CCR+z); |
| BSET(p->uses,GPR+q1); |
| return (1); |
| } |
| } |
| |
| if ((n = sscanf(p->txt," cr%15s %d,%d,%d",buf,&z,&q1,&q2)) >= 2) { |
| /* condition code register operation (vbcc uses this version) */ |
| p->latency = 1; |
| BSET(p->pipes,SRU); |
| BSET(p->modifies,CCR+(z>>4)); |
| if (n >= 3) { |
| BSET(p->uses,CCR+(q1>>4)); |
| if (n == 4) |
| BSET(p->uses,CCR+(q2>>4)); |
| } |
| return (1); |
| } |
| |
| if (sscanf(p->txt,elf ? " rlw%15s %d,%d,%d,%d,%d" : |
| " rlw%15s r%d,r%d,%d,%d,%d",buf,&z,&q1,&i,&n,&x) == 6) { |
| /* rotate left: rlwimi, rlwinm, rlwnm r1,r2,x,y,z */ |
| p->latency = 1; |
| BSET(p->pipes,IU); |
| if (*(strest(buf,1)) == '.') |
| BSET(p->modifies,CCR); |
| BSET(p->uses,GPR+q1); |
| BSET(p->modifies,GPR+z); |
| return (1); |
| } |
| |
| if (sscanf(p->txt,elf ? " %15s %d,%d,%c" : " %15s r%d,r%d,%c", |
| buf,&z,&q1,&c) == 4) { |
| /* op r1,r2,imm */ |
| if (!strncmp(buf,"addi",4) || |
| !strncmp(buf,"andi",4) || |
| !strncmp(buf,"mulli",5) || |
| !strncmp(buf,"ori",3) || |
| !strncmp(buf,"slwi",4) || |
| !strncmp(buf,"srwi",4) || |
| !strncmp(buf,"srawi",5) || |
| !strncmp(buf,"subi",4) || |
| !strncmp(buf,"xori",4)) { |
| char *a = strest(buf,1); |
| |
| if (*buf == 'm') /* mulli */ |
| p->latency = 3; |
| else |
| p->latency = 1; |
| BSET(p->pipes,IU); |
| if (!strncmp(buf,"add",3) && *(buf+4)!='c') |
| BSET(p->pipes,SRU); /* addi/addis may also execute in SRU */ |
| if (*a == '.') { |
| BSET(p->modifies,CCR); |
| --a; |
| } |
| if (*a == 'c') |
| BSET(p->modifies,XER); |
| BSET(p->uses,GPR+q1); |
| BSET(p->modifies,GPR+z); |
| return (1); |
| } |
| } |
| |
| if (sscanf(p->txt,elf ? " %15s %d,0,%d" : " %15s r%d,0,r%d", |
| buf,&z,&q2) == 3) { |
| /* op r1,0,r3 */ |
| if (!strncmp(buf,"add",3) || |
| !strncmp(buf,"sub",3)) { |
| p->latency = 1; |
| BSET(p->pipes,IU); |
| if (*(strest(buf,1)) == '.') |
| BSET(p->modifies,CCR); |
| else |
| BSET(p->pipes,SRU); /* add/addo may also execute in SRU */ |
| BSET(p->uses,GPR+q2); |
| BSET(p->modifies,GPR+z); |
| return (1); |
| } |
| } |
| |
| if (sscanf(p->txt,elf ? " %15s %d,%d,%d" : " %15s r%d,r%d,r%d", |
| buf,&z,&q1,&q2) == 4) { |
| /* op r1,r2,r3 */ |
| if (!strncmp(buf,"add",3) || |
| !strncmp(buf,"and",3) || |
| !strncmp(buf,"div",3) || |
| !strncmp(buf,"eqv",3) || |
| !strncmp(buf,"mul",3) || |
| !strncmp(buf,"nand",4) || |
| !strncmp(buf,"nor",3) || |
| !strncmp(buf,"or",2) || |
| !strncmp(buf,"sl",2) || |
| !strncmp(buf,"sr",2) || |
| !strncmp(buf,"sub",3) || |
| !strncmp(buf,"xor",3)) { |
| char *a = strest(buf,1); |
| |
| if (!strncmp(buf,"mul",3)) { |
| if (*(buf+5) == 'u') |
| p->latency = 6; /* mulhwu needs 6 cycles */ |
| else |
| p->latency = 5; |
| if (*(buf+3) == 'l') |
| BSET(p->modifies,XER); |
| } |
| else if (!strncmp(buf,"div",3)) { |
| /* p->latency = 37;*/ |
| p->latency = 20; /* 603e has 20 since PID7 */ |
| BSET(p->modifies,XER); |
| } |
| else |
| p->latency = 1; |
| BSET(p->pipes,IU); |
| if (!strcmp(buf,"add") || !strcmp(buf,"addo")) |
| BSET(p->pipes,SRU); /* add/addo may also execute in SRU */ |
| |
| if (*a == '.') { |
| BSET(p->modifies,CCR); |
| --a; |
| } |
| if (*a == 'o') { |
| BSET(p->modifies,XER); |
| --a; |
| } |
| if (*a == 'c') { |
| BSET(p->modifies,XER); |
| --a; |
| } |
| if (*a == 'e') |
| BSET(p->uses,XER); |
| BSET(p->uses,GPR+q1); |
| BSET(p->uses,GPR+q2); |
| BSET(p->modifies,GPR+z); |
| return (1); |
| } |
| } |
| |
| if (sscanf(p->txt,elf ? " l%15s %d,%c" : " l%15s r%d,%c", |
| buf,&z,&c) == 3) { |
| if (*buf == 'i') { |
| /* li, lis -> addi, addis */ |
| p->latency = 1; |
| BSET(p->pipes,IU); |
| BSET(p->pipes,SRU); |
| BSET(p->modifies,GPR+z); |
| return (1); |
| } |
| } |
| |
| if (sscanf(p->txt,elf ? " %15s %d,%d" : " %15s r%d,r%d", |
| buf,&z,&q1) == 3) { |
| /* op r1,r2 */ |
| if (!strncmp(buf,"add",3) || |
| !strncmp(buf,"exts",4) || |
| !strncmp(buf,"mr",2) || |
| !strncmp(buf,"neg",3) || |
| !strncmp(buf,"sub",3)) { |
| char *a = strest(buf,1); |
| |
| p->latency = 1; |
| if (*buf=='a' || *buf=='s') |
| BSET(p->uses,XER); /* addme/addze/subfme/subfze/... */ |
| BSET(p->pipes,IU); |
| if (*a == '.') { |
| BSET(p->modifies,CCR); |
| --a; |
| } |
| if (*a == 'o') { |
| BSET(p->modifies,XER); |
| } |
| BSET(p->uses,GPR+q1); |
| BSET(p->modifies,GPR+z); |
| return (1); |
| } |
| } |
| |
| if (sscanf(p->txt,elf?" m%15s %d":" m%15s r%d",buf,&z) == 2) { |
| /* mtxxx, mfxxx: move from/to special registers */ |
| int reg=0; |
| |
| if (!strcmp(&buf[1],"xer")) |
| reg = XER; |
| else if (!strcmp(&buf[1],"ctr")) |
| reg = CTR; |
| else if (!strcmp(&buf[1],"lr")) |
| reg = LR; |
| else if (!strncmp(&buf[1],"fs",2)) |
| reg = FPSCR; |
| if (reg) { |
| if (reg == FPSCR) { |
| p->latency = 3; |
| BSET(p->pipes,FPU); |
| /*if (*buf == 'f') { |
| BSET(p->uses,reg); |
| BSET(p->modifies,z); |
| } |
| else {*/ |
| BSET(p->uses,z); |
| BSET(p->modifies,reg); |
| /*}*/ |
| } |
| else { |
| BSET(p->pipes,SRU); |
| if (*buf == 'f') { |
| p->latency = 1; |
| BSET(p->uses,reg); |
| BSET(p->modifies,z); |
| } |
| else { |
| p->latency = 2; |
| BSET(p->uses,z); |
| BSET(p->modifies,reg); |
| } |
| } |
| return (1); |
| } |
| } |
| } |
| |
| |
| else if (cpu == 604) { |
| /* scheduling for the PowerPC 604 */ |
| |
| if ((!elf && sscanf(p->txt," %15s %c%d,%39s",buf,&c,&z,oper) == 4) || |
| (elf && sscanf(p->txt," %15s %d,%39s",buf,&z,oper) == 3)) { |
| if (elf) { |
| if ((buf[0]=='l' && buf[1]=='f') || (buf[0]=='s' && buf[2]=='f')) |
| c = 'f'; |
| else |
| c = 'r'; |
| } |
| if ((q1 = lsreg(oper))>=0 && (c=='r'||c=='f')) { |
| /* load/store instruction ...,d(rQ1) */ |
| |
| if (!strcmp(buf,"la")) { |
| /* la rZ,d(rQ1) is the same as: addi rZ,rQ1,d */ |
| p->latency = 1; |
| BSET(p->pipes,SCIU1); |
| BSET(p->pipes,SCIU2); |
| BSET(p->uses,GPR+q1); |
| BSET(p->modifies,GPR+z); |
| return (1); |
| } |
| |
| BSET(p->pipes,LSU); |
| if (*(strest(buf,1)) == 'u') /* update instruction? */ |
| BSET(p->modifies,GPR+q1); |
| else |
| BSET(p->uses,GPR+q1); |
| |
| if (c == 'r') { |
| /* integer load/store */ |
| |
| if (!strncmp(strest(buf,2),"mw",2)) { |
| /* load/store multiple word rz,i(rq1) */ |
| |
| p->latency = 2+(32-z); |
| if (*buf == 'l') { |
| for (x=z; x<32; x++) |
| BSET(p->modifies,GPR+x); |
| BSET(p->uses,MEM); |
| } |
| else { |
| for (x=z; x<32; x++) |
| BSET(p->uses,GPR+x); |
| BSET(p->modifies,MEM); |
| } |
| } |
| else { |
| /* load/store integer rz,i(rq1) */ |
| |
| if(*buf == 'l') { |
| p->latency = 2; |
| BSET(p->modifies,GPR+z); |
| BSET(p->uses,MEM); |
| } |
| else{ |
| p->latency = 3; |
| BSET(p->uses,GPR+z); |
| BSET(p->modifies,MEM); |
| } |
| } |
| } |
| |
| else { |
| /* load/store float fz,d(rQ1) */ |
| |
| p->latency = 3; |
| if(*buf == 'l') { |
| BSET(p->modifies,FPR+z); |
| BSET(p->uses,MEM); |
| } |
| else{ |
| BSET(p->uses,FPR+z); |
| BSET(p->modifies,MEM); |
| } |
| } |
| |
| return (1); |
| } |
| } |
| |
| if ((!elf && sscanf(p->txt," %15s %c%d,r%d,r%d",buf,&c,&z,&q1,&q2) == 5) || |
| (elf && sscanf(p->txt," %15s %d,%d,%d",buf,&z,&q1,&q2) == 4)) { |
| if (*buf=='l' || (buf[0]=='s' && buf[1]=='t')) { |
| if (elf) { |
| if ((buf[0]=='l' && buf[1]=='f') || (buf[0]=='s' && buf[2]=='f')) |
| c = 'f'; |
| else |
| c = 'r'; |
| } |
| |
| BSET(p->pipes,LSU); |
| BSET(p->uses,GPR+q2); |
| if (!strncmp(strest(buf,2),"ux",2)) /* update instruction? */ |
| BSET(p->modifies,GPR+q1); |
| else |
| BSET(p->uses,GPR+q1); |
| |
| if (c == 'r') { |
| /* integer load/store */ |
| |
| if (!strncmp(buf,"lsw",3) || !strncmp(buf,"stsw",4)) { |
| /* load/store string word rz,rq1,rq2/imm */ |
| p->flags = BARRIER; /* too complex... ;) */ |
| return (1); |
| } |
| else { |
| /* load/store integer indexed rz,rq1,rq2 */ |
| |
| if(*buf == 'l') { |
| p->latency = 2; |
| BSET(p->modifies,GPR+z); |
| BSET(p->uses,MEM); |
| } |
| else{ |
| p->latency = 3; |
| BSET(p->uses,GPR+z); |
| BSET(p->modifies,MEM); |
| } |
| return (1); |
| } |
| } |
| |
| else if (c == 'f') { |
| /* load/store float indexed fz,rq1,rq2 */ |
| p->latency = 3; |
| if(*buf == 'l') { |
| BSET(p->modifies,FPR+z); |
| BSET(p->uses,MEM); |
| } |
| else{ |
| BSET(p->uses,FPR+z); |
| BSET(p->modifies,MEM); |
| } |
| return (1); |
| } |
| } |
| } |
| |
| if (sscanf(p->txt,elf ? " fcm%15s %d,%d,%d" : " fcm%15s cr%d,f%d,f%d", |
| buf,&z,&q1,&q2) == 4) { |
| /* floating point compare CR0 */ |
| p->latency = 3; |
| BSET(p->pipes,FPU); |
| BSET(p->modifies,CCR+z); |
| /*BSET(p->modifies,FPSCR);*/ |
| BSET(p->uses,FPR+q1); |
| BSET(p->uses,FPR+q2); |
| return (1); |
| } |
| if (sscanf(p->txt,elf ? " fcm%15s %d,%d" : " fcm%15s f%d,f%d", |
| buf,&q1,&q2) == 3) { |
| /* floating point compare */ |
| p->latency = 3; |
| BSET(p->pipes,FPU); |
| BSET(p->modifies,CCR); |
| /*BSET(p->modifies,FPSCR);*/ |
| BSET(p->uses,FPR+q1); |
| BSET(p->uses,FPR+q2); |
| return (1); |
| } |
| |
| if ((n = sscanf(p->txt,elf ? " f%15s %d,%d,%d,%d" : |
| " f%15s f%d,f%d,f%d,f%d",buf,&z,&q1,&q2,&q3))>=3) { |
| /* floating point operation with 2, 3 or 4 operands */ |
| |
| #if 0 |
| if (strncmp(buf,"abs",3) && |
| strncmp(buf,"mr",2) && |
| strncmp(buf,"nabs",4) && |
| strncmp(buf,"neg",3) && |
| strncmp(buf,"sel",3)) |
| BSET(p->modifies,FPSCR); /* only some instr. don't alter FPSCR */ |
| #endif |
| |
| if (!strncmp(buf,"divs",4) || |
| !strncmp(buf,"res",3)) |
| p->latency = 18; |
| else if (!strncmp(buf,"div",3)) |
| p->latency = 32; |
| else |
| p->latency = 3; |
| |
| if (*(strest(buf,1)) == '.') |
| BSET(p->modifies,CCR+1); |
| BSET(p->pipes,FPU); |
| BSET(p->uses,FPR+q1); |
| if (n >= 4) { |
| BSET(p->uses,FPR+q2); |
| if (n == 5) |
| BSET(p->uses,FPR+q3); |
| } |
| BSET(p->modifies,FPR+z); |
| return (1); |
| } |
| |
| if (sscanf(p->txt,elf ? " cm%15s %d,%d,%d" : " cm%15s cr%d,r%d,r%d", |
| buf,&z,&q1,&q2) == 4) { |
| /* integer compare instruction */ |
| p->latency = 1; |
| BSET(p->pipes,SCIU1); |
| BSET(p->pipes,SCIU2); |
| BSET(p->modifies,CCR+z); |
| BSET(p->uses,GPR+q1); |
| if (*(strest(buf,1)) != 'i') |
| BSET(p->uses,GPR+q2); |
| return (1); |
| } |
| if (sscanf(p->txt,elf ? " cm%15s %d,%d" : " cm%15s r%d,r%d", |
| buf,&q1,&q2) == 3) { |
| /* integer compare instruction CR0 */ |
| p->latency = 1; |
| BSET(p->pipes,SCIU1); |
| BSET(p->pipes,SCIU2); |
| BSET(p->modifies,CCR); |
| BSET(p->uses,GPR+q1); |
| if (*(strest(buf,1)) != 'i') |
| BSET(p->uses,GPR+q2); |
| return (1); |
| } |
| |
| if (!elf) { |
| if (sscanf(p->txt," cm%15s cr%d,r%d,%d",buf,&z,&q1,&i) == 4) { |
| /* immediate integer compare instruction */ |
| p->latency = 1; |
| BSET(p->pipes,SCIU1); |
| BSET(p->pipes,SCIU2); |
| BSET(p->modifies,CCR+z); |
| BSET(p->uses,GPR+q1); |
| return (1); |
| } |
| if (sscanf(p->txt," cm%15s r%d,%d",buf,&q1,&i) == 3) { |
| /* immediate integer compare instruction CR0 */ |
| p->latency = 1; |
| BSET(p->pipes,SCIU1); |
| BSET(p->pipes,SCIU2); |
| BSET(p->modifies,CCR+z); |
| BSET(p->uses,GPR+q1); |
| |
| return (1); |
| } |
| } |
| |
| if ((n = sscanf(p->txt," cr%15s %d,%d,%d",buf,&z,&q1,&q2)) >= 2) { |
| /* condition code register operation (vbcc uses this version) */ |
| p->latency = 1; |
| BSET(p->pipes,CRU); |
| BSET(p->modifies,CCR+(z>>4)); |
| if (n >= 3) { |
| BSET(p->uses,CCR+(q1>>4)); |
| if (n == 4) |
| BSET(p->uses,CCR+(q2>>4)); |
| } |
| return (1); |
| } |
| |
| if (sscanf(p->txt,elf ? " rlw%15s %d,%d,%d,%d,%d" : |
| " rlw%15s r%d,r%d,%d,%d,%d",buf,&z,&q1,&i,&n,&x) == 6) { |
| /* rotate left: rlwimi, rlwinm, rlwnm r1,r2,x,y,z */ |
| p->latency = 1; |
| BSET(p->pipes,SCIU1); |
| BSET(p->pipes,SCIU2); |
| if (*(strest(buf,1)) == '.') |
| BSET(p->modifies,CCR); |
| BSET(p->uses,GPR+q1); |
| BSET(p->modifies,GPR+z); |
| return (1); |
| } |
| |
| if (sscanf(p->txt,elf ? " %15s %d,%d,%c" : " %15s r%d,r%d,%c", |
| buf,&z,&q1,&c) == 4) { |
| /* op r1,r2,imm */ |
| if (!strncmp(buf,"addi",4) || |
| !strncmp(buf,"andi",4) || |
| !strncmp(buf,"mulli",5) || |
| !strncmp(buf,"ori",3) || |
| !strncmp(buf,"slwi",4) || |
| !strncmp(buf,"srwi",4) || |
| !strncmp(buf,"srawi",5) || |
| !strncmp(buf,"subi",4) || |
| !strncmp(buf,"xori",4)) { |
| char *a = strest(buf,1); |
| |
| if (*buf == 'm') { /* mulli */ |
| p->latency = 3; |
| BSET(p->pipes,MCIU); |
| } |
| else { |
| p->latency = 1; |
| BSET(p->pipes,SCIU1); |
| BSET(p->pipes,SCIU2); |
| } |
| if (*a == '.') { |
| BSET(p->modifies,CCR); |
| --a; |
| } |
| if (*a == 'c') |
| BSET(p->modifies,XER); |
| BSET(p->uses,GPR+q1); |
| BSET(p->modifies,GPR+z); |
| return (1); |
| } |
| } |
| |
| if (sscanf(p->txt,elf ? " %15s %d,0,%d" : " %15s r%d,0,r%d", |
| buf,&z,&q2) == 3) { |
| /* op r1,0,r3 */ |
| if (!strncmp(buf,"add",3) || |
| !strncmp(buf,"sub",3)) { |
| p->latency = 1; |
| BSET(p->pipes,SCIU1); |
| BSET(p->pipes,SCIU2); |
| if (*(strest(buf,1)) == '.') |
| BSET(p->modifies,CCR); |
| else |
| BSET(p->pipes,SRU); /* add/addo may also execute in SRU */ |
| BSET(p->uses,GPR+q2); |
| BSET(p->modifies,GPR+z); |
| return (1); |
| } |
| } |
| |
| if (sscanf(p->txt,elf ? " %15s %d,%d,%d" : " %15s r%d,r%d,r%d", |
| buf,&z,&q1,&q2) == 4) { |
| /* op r1,r2,r3 */ |
| if (!strncmp(buf,"add",3) || |
| !strncmp(buf,"and",3) || |
| !strncmp(buf,"div",3) || |
| !strncmp(buf,"eqv",3) || |
| !strncmp(buf,"mul",3) || |
| !strncmp(buf,"nand",4) || |
| !strncmp(buf,"nor",3) || |
| !strncmp(buf,"or",2) || |
| !strncmp(buf,"sl",2) || |
| !strncmp(buf,"sr",2) || |
| !strncmp(buf,"sub",3) || |
| !strncmp(buf,"xor",3)) { |
| char *a = strest(buf,1); |
| |
| if (!strncmp(buf,"mul",3)) { |
| p->latency = 4; |
| BSET(p->pipes,MCIU); |
| if (*(buf+3) == 'l') |
| BSET(p->modifies,XER); |
| } |
| else if (!strncmp(buf,"div",3)) { |
| p->latency = 20; |
| BSET(p->pipes,MCIU); |
| BSET(p->modifies,XER); |
| } |
| else { |
| p->latency = 1; |
| BSET(p->pipes,SCIU1); |
| BSET(p->pipes,SCIU2); |
| } |
| if (*a == '.') { |
| BSET(p->modifies,CCR); |
| --a; |
| } |
| if (*a == 'o') { |
| BSET(p->modifies,XER); |
| --a; |
| } |
| if (*a == 'c') { |
| BSET(p->modifies,XER); |
| --a; |
| } |
| if (*a == 'e') |
| BSET(p->uses,XER); |
| BSET(p->uses,GPR+q1); |
| BSET(p->uses,GPR+q2); |
| BSET(p->modifies,GPR+z); |
| return (1); |
| } |
| } |
| |
| if (sscanf(p->txt,elf ? " l%15s %d,%c" : " l%15s r%d,%c", |
| buf,&z,&c) == 3) { |
| if (*buf == 'i') { |
| /* li, lis -> addi, addis */ |
| p->latency = 1; |
| BSET(p->pipes,SCIU1); |
| BSET(p->pipes,SCIU2); |
| BSET(p->modifies,GPR+z); |
| return (1); |
| } |
| } |
| |
| if (sscanf(p->txt,elf ? " %15s %d,%d" : " %15s r%d,r%d", |
| buf,&z,&q1) == 3) { |
| /* op r1,r2 */ |
| if (!strncmp(buf,"add",3) || |
| !strncmp(buf,"exts",4) || |
| !strncmp(buf,"mr",2) || |
| !strncmp(buf,"neg",3) || |
| !strncmp(buf,"sub",3)) { |
| char *a = strest(buf,1); |
| |
| p->latency = 1; |
| BSET(p->pipes,SCIU1); |
| BSET(p->pipes,SCIU2); |
| if (*buf=='a' || *buf=='s') |
| BSET(p->uses,XER); /* addme/addze/subfme/subfze/... */ |
| if (*a == '.') { |
| BSET(p->modifies,CCR); |
| --a; |
| } |
| if (*a == 'o') { |
| BSET(p->modifies,XER); |
| } |
| BSET(p->uses,GPR+q1); |
| BSET(p->modifies,GPR+z); |
| return (1); |
| } |
| } |
| |
| if (sscanf(p->txt,elf?" m%15s %d":" m%15s r%d",buf,&z) == 2) { |
| /* mtxxx, mfxxx: move from/to special registers */ |
| int reg=0; |
| |
| if (!strcmp(&buf[1],"xer")) |
| reg = XER; |
| else if (!strcmp(&buf[1],"ctr")) |
| reg = CTR; |
| else if (!strcmp(&buf[1],"lr")) |
| reg = LR; |
| else if (!strncmp(&buf[1],"fs",2)) |
| reg = FPSCR; |
| if (reg) { |
| if (reg == FPSCR) { |
| p->latency = 3; |
| BSET(p->pipes,FPU); |
| /*if (*buf == 'f') { |
| BSET(p->uses,reg); |
| BSET(p->modifies,z); |
| } |
| else {*/ |
| BSET(p->uses,z); |
| BSET(p->modifies,reg); |
| /*}*/ |
| } |
| else { |
| BSET(p->pipes,MCIU); |
| if (*buf == 'f') { |
| p->latency = 3; |
| BSET(p->uses,reg); |
| BSET(p->modifies,z); |
| } |
| else { |
| p->latency = 1; |
| BSET(p->uses,z); |
| BSET(p->modifies,reg); |
| } |
| } |
| return (1); |
| } |
| } |
| } |
| |
| p->flags = BARRIER; |
| return (1); |
| } |