Import VBCC source snapshot (29/04/2022)
diff --git a/machines/ppc/schedule.c b/machines/ppc/schedule.c
new file mode 100755
index 0000000..e7172d3
--- /dev/null
+++ b/machines/ppc/schedule.c
@@ -0,0 +1,1158 @@
+/*
+ * 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);
+}