diff options
| author | forsyth <forsyth@vitanuova.com> | 2010-04-27 12:51:13 +0100 |
|---|---|---|
| committer | forsyth <forsyth@vitanuova.com> | 2010-04-27 12:51:13 +0100 |
| commit | d67b7dad77bb8aa973dad1f7c3ab0c309b114278 (patch) | |
| tree | 6794120fb327d6de19cf05eed53f80d877781a3e /utils | |
| parent | 09da2e137d5eb0c940df35d989e4c31ec0654fc4 (diff) | |
20100427-1251
Diffstat (limited to 'utils')
123 files changed, 6667 insertions, 3404 deletions
diff --git a/utils/0c/gc.h b/utils/0c/gc.h index 88196aec..23f0bdd9 100644 --- a/utils/0c/gc.h +++ b/utils/0c/gc.h @@ -258,7 +258,7 @@ void gpseudo(int, Sym*, Node*); int swcmp(const void*, const void*); void doswit(Node*); void swit1(C1*, int, long, Node*, Node*); -void cas(void); +void casf(void); void bitload(Node*, Node*, Node*, Node*, Node*); void bitstore(Node*, Node*, Node*, Node*, Node*); long outstring(char*, long); diff --git a/utils/0c/peep.c b/utils/0c/peep.c index a7a60403..0ab12696 100644 --- a/utils/0c/peep.c +++ b/utils/0c/peep.c @@ -570,7 +570,7 @@ copyu(Prog *p, Adr *v, Adr *s) return 3; return 0; } - return 0; + /* not reached */ } int diff --git a/utils/0c/sgen.c b/utils/0c/sgen.c index eb562e8f..608846cc 100644 --- a/utils/0c/sgen.c +++ b/utils/0c/sgen.c @@ -154,7 +154,7 @@ loop: if(cases == C) diag(n, "case/default outside a switch"); if(l == Z) { - cas(); + casf(); cases->val = 0; cases->def = 1; cases->label = pc; @@ -165,7 +165,7 @@ loop: goto rloop; if(l->op == OCONST) if(typechl[l->type->etype]) { - cas(); + casf(); cases->val = l->vconst; cases->def = 0; cases->label = pc; @@ -189,7 +189,7 @@ loop: cn = cases; cases = C; - cas(); + casf(); sbc = breakpc; breakpc = pc; diff --git a/utils/0c/swt.c b/utils/0c/swt.c index 38cd3d43..2e24fedd 100644 --- a/utils/0c/swt.c +++ b/utils/0c/swt.c @@ -93,7 +93,7 @@ swit1(C1 *q, int nc, long def, Node *n, Node *tn) } void -cas(void) +casf(void) { Case *c; diff --git a/utils/1c/gc.h b/utils/1c/gc.h index 288971f3..ca2c84fb 100644 --- a/utils/1c/gc.h +++ b/utils/1c/gc.h @@ -280,7 +280,7 @@ Node* nodconst(long); int swcmp(const void*, const void*); void doswit(int, Node*); void swit1(C1*, int, long, int, Node*); -void cas(void); +void casf(void); int bitload(Node*, int, int, int, Node*); void bitstore(Node*, int, int, int, int, Node*); long outstring(char*, long); diff --git a/utils/1c/peep.c b/utils/1c/peep.c index e0a535c2..7583da5d 100644 --- a/utils/1c/peep.c +++ b/utils/1c/peep.c @@ -565,9 +565,6 @@ anyvar(Adr *a) if(regtyp(a->type)) return 1; return 0; - if(a->type == D_AUTO || a->type == D_PARAM) - return 1; - return 0; } /* diff --git a/utils/1c/sgen.c b/utils/1c/sgen.c index b7da4762..cb289eaa 100644 --- a/utils/1c/sgen.c +++ b/utils/1c/sgen.c @@ -131,7 +131,7 @@ loop: if(cases == C) diag(n, "case/default outside a switch"); if(l == Z) { - cas(); + casf(); cases->val = 0; cases->def = 1; cases->label = pc; @@ -143,7 +143,7 @@ loop: goto rloop; if(l->op == OCONST) if(typechl[l->type->etype]) { - cas(); + casf(); cases->val = l->vconst; cases->def = 0; cases->label = pc; @@ -174,7 +174,7 @@ loop: cn = cases; cases = C; - cas(); + casf(); sbc = breakpc; breakpc = pc; diff --git a/utils/1c/swt.c b/utils/1c/swt.c index dc735a29..34daeb1e 100644 --- a/utils/1c/swt.c +++ b/utils/1c/swt.c @@ -106,7 +106,7 @@ linear: } void -cas(void) +casf(void) { Case *c; diff --git a/utils/1l/asm.c b/utils/1l/asm.c index f8dba670..6cf02ed8 100644 --- a/utils/1l/asm.c +++ b/utils/1l/asm.c @@ -1259,11 +1259,6 @@ asmea(Prog *p, Adr *a) diag("unknown addressing mode: %d in %s", t, TNAME); return 0; - if(!debug['a']) - print("%P\n", p); - diag("bad operand in %s", TNAME); - return 0; - toobig: if(!debug['a']) print("%P\n", p); diff --git a/utils/1l/obj.c b/utils/1l/obj.c index 379a9ffb..afc3c9e7 100644 --- a/utils/1l/obj.c +++ b/utils/1l/obj.c @@ -1001,7 +1001,7 @@ loop: pc++; goto loop; } - goto loop; + /* not reached */ eof: diag("%s: truncated object file in %s", pn, TNAME); diff --git a/utils/2c/gc.h b/utils/2c/gc.h index ab30649e..75dd85c0 100644 --- a/utils/2c/gc.h +++ b/utils/2c/gc.h @@ -297,7 +297,7 @@ Node* nodconst(long); int swcmp(const void*, const void*); void doswit(int, Node*); void swit1(C1*, int, long, int, Node*); -void cas(void); +void casf(void); int bitload(Node*, int, int, int, Node*); void bitstore(Node*, int, int, int, int, Node*); long outstring(char*, long); diff --git a/utils/2c/peep.c b/utils/2c/peep.c index 4bde0d40..7026e628 100644 --- a/utils/2c/peep.c +++ b/utils/2c/peep.c @@ -572,9 +572,6 @@ anyvar(Adr *a) if(regtyp(a->type)) return 1; return 0; - if(a->type == D_AUTO || a->type == D_PARAM) - return 1; - return 0; } /* diff --git a/utils/2c/sgen.c b/utils/2c/sgen.c index 85925f72..b4020a99 100644 --- a/utils/2c/sgen.c +++ b/utils/2c/sgen.c @@ -131,7 +131,7 @@ loop: if(cases == C) diag(n, "case/default outside a switch"); if(l == Z) { - cas(); + casf(); cases->val = 0; cases->def = 1; cases->label = pc; @@ -143,7 +143,7 @@ loop: goto rloop; if(l->op == OCONST) if(typechl[l->type->etype]) { - cas(); + casf(); cases->val = l->vconst; cases->def = 0; cases->label = pc; @@ -174,7 +174,7 @@ loop: cn = cases; cases = C; - cas(); + casf(); sbc = breakpc; breakpc = pc; diff --git a/utils/2c/swt.c b/utils/2c/swt.c index 442d1fea..ca6895f9 100644 --- a/utils/2c/swt.c +++ b/utils/2c/swt.c @@ -186,7 +186,7 @@ linear: } void -cas(void) +casf(void) { Case *c; diff --git a/utils/2l/obj.c b/utils/2l/obj.c index f51d028b..9cc85565 100644 --- a/utils/2l/obj.c +++ b/utils/2l/obj.c @@ -1025,7 +1025,7 @@ loop: pc++; goto loop; } - goto loop; + /* not reached */ eof: diag("%s: truncated object file in %s", pn, TNAME); diff --git a/utils/5c/gc.h b/utils/5c/gc.h index 1231ac31..cbaf7a87 100644 --- a/utils/5c/gc.h +++ b/utils/5c/gc.h @@ -266,7 +266,7 @@ void gpseudo(int, Sym*, Node*); int swcmp(const void*, const void*); void doswit(Node*); void swit1(C1*, int, long, Node*, Node*); -void cas(void); +void casf(void); void bitload(Node*, Node*, Node*, Node*, Node*); void bitstore(Node*, Node*, Node*, Node*, Node*); long outstring(char*, long); diff --git a/utils/5c/peep.c b/utils/5c/peep.c index ba22e40d..25e5a118 100644 --- a/utils/5c/peep.c +++ b/utils/5c/peep.c @@ -1091,7 +1091,7 @@ copyu(Prog *p, Adr *v, Adr *s) return 3; return 0; } - return 0; + /* not reached */ } int diff --git a/utils/5c/sgen.c b/utils/5c/sgen.c index b20865d9..e5d48eeb 100644 --- a/utils/5c/sgen.c +++ b/utils/5c/sgen.c @@ -174,7 +174,7 @@ loop: if(cases == C) diag(n, "case/default outside a switch"); if(l == Z) { - cas(); + casf(); cases->val = 0; cases->def = 1; cases->label = pc; @@ -185,7 +185,7 @@ loop: goto rloop; if(l->op == OCONST) if(typechl[l->type->etype]) { - cas(); + casf(); cases->val = l->vconst; cases->def = 0; cases->label = pc; @@ -209,7 +209,7 @@ loop: cn = cases; cases = C; - cas(); + casf(); sbc = breakpc; breakpc = pc; diff --git a/utils/5c/swt.c b/utils/5c/swt.c index 5ee0e39f..87b34458 100644 --- a/utils/5c/swt.c +++ b/utils/5c/swt.c @@ -123,7 +123,7 @@ direct: } void -cas(void) +casf(void) { Case *c; diff --git a/utils/5coff/5coff.c b/utils/5coff/5coff.c index cae73108..540ed02b 100644 --- a/utils/5coff/5coff.c +++ b/utils/5coff/5coff.c @@ -126,7 +126,7 @@ get_file(char *ifile) h = crackhdr(ifd, &ihdr); if (!h || dflag){ fprint(2, "Crackhdr: %d, type: %d, name: %s\n", h, ihdr.type, ihdr.name); - fprint(2, "txt %lux, ent %lux, txtsz %lux, dataddr %lux\n", + fprint(2, "txt %llux, ent %llux, txtsz %lux, dataddr %llux\n", ihdr.txtaddr, ihdr.entry, ihdr.txtsz, ihdr.dataddr); } if (!h) @@ -159,7 +159,7 @@ get_file(char *ifile) } if(0){ print("H=%lux T=%lux D=%lux t=%lux d=%lux b=%lux e=%lux\n", HEADR, INITTEXT, INITDAT, textsize, datsize, bsssize, INITENTRY); - print("%lux %lux %lux %lux %lux %lux\n", ihdr.txtaddr, ihdr.dataddr, ihdr.entry, ihdr.txtsz, ihdr.datsz, ihdr.bsssz); + print("%llux %llux %llux %lux %lux %lux\n", ihdr.txtaddr, ihdr.dataddr, ihdr.entry, ihdr.txtsz, ihdr.datsz, ihdr.bsssz); } readsyms(); diff --git a/utils/5cv/5cv.c b/utils/5cv/5cv.c index 1edbf6c6..67b400ab 100644 --- a/utils/5cv/5cv.c +++ b/utils/5cv/5cv.c @@ -107,7 +107,7 @@ get_file(char *ifile) h = crackhdr(Ifd, &Ihdr); if (!h || Debug){ fprint(2, "Crackhdr: %d, type: %d, name: %s\n", h, Ihdr.type, Ihdr.name); - fprint(2, "txt %lux, ent %lux, txtsz %lux, dataddr %lux\n", + fprint(2, "txt %llux, ent %llux, txtsz %lux, dataddr %llux\n", Ihdr.txtaddr, Ihdr.entry, Ihdr.txtsz, Ihdr.dataddr); } if (!h) diff --git a/utils/5l/obj.c b/utils/5l/obj.c index 2eadf877..35c5f558 100644 --- a/utils/5l/obj.c +++ b/utils/5l/obj.c @@ -844,7 +844,7 @@ loop: bloc += r; c -= r; - if(p->reg < 0 || p->reg > NREG) + if(p->reg > NREG) diag("register out of range %d", p->reg); p->link = P; diff --git a/utils/5l/thumb.c b/utils/5l/thumb.c index 9ec8ce5b..f16175ea 100644 --- a/utils/5l/thumb.c +++ b/utils/5l/thumb.c @@ -469,31 +469,30 @@ brextra(Prog *p) diag("bad op in brextra()"); c = thumbaclass(&p->to, p); switch(p->as){ - case AB: - if(c != C_SBRA) - return 0; - return 8-2+2; - case ABL: - if(c != C_SBRA) - return 0; - return 14-4+2; - case ABX: - if(c == C_REG || c == C_HREG) - return 0; + case AB: + if(c != C_SBRA) + return 0; + return 8-2+2; + case ABL: + if(c != C_SBRA) + return 0; + return 14-4+2; + case ABX: + if(c == C_REG || c == C_HREG) + return 0; #ifdef CALLEEBX - diag("ABX $I in brextra"); + diag("ABX $I in brextra"); #endif - if(c != C_SBRA) - return 0; - return 14-10+2; - default: - if(c == C_GBRA) - return 0; - if(c == C_LBRA) - return 10-4+2; - return 10-2+2; + if(c != C_SBRA) + return 0; + return 14-10+2; + default: + if(c == C_GBRA) + return 0; + if(c == C_LBRA) + return 10-4+2; + return 10-2+2; } - return 0; } #define high(r) ((r)>=8) diff --git a/utils/6c/gc.h b/utils/6c/gc.h index 769a38c0..f338707b 100644 --- a/utils/6c/gc.h +++ b/utils/6c/gc.h @@ -273,7 +273,7 @@ void gpseudo(int, Sym*, Node*); int swcmp(const void*, const void*); void doswit(Node*); void swit1(C1*, int, long, Node*); -void cas(void); +void casf(void); void bitload(Node*, Node*, Node*, Node*, Node*); void bitstore(Node*, Node*, Node*, Node*, Node*); long outstring(char*, long); diff --git a/utils/6c/sgen.c b/utils/6c/sgen.c index dcfc0abc..52f53faf 100644 --- a/utils/6c/sgen.c +++ b/utils/6c/sgen.c @@ -174,7 +174,7 @@ loop: if(cases == C) diag(n, "case/default outside a switch"); if(l == Z) { - cas(); + casf(); cases->val = 0; cases->def = 1; cases->label = pc; @@ -186,7 +186,7 @@ loop: goto rloop; if(l->op == OCONST) if(typechlv[l->type->etype]) { - cas(); + casf(); cases->val = l->vconst; cases->def = 0; cases->label = pc; @@ -211,7 +211,7 @@ loop: cn = cases; cases = C; - cas(); + casf(); sbc = breakpc; breakpc = pc; diff --git a/utils/6c/swt.c b/utils/6c/swt.c index 5a9c3fd2..711b0ee1 100644 --- a/utils/6c/swt.c +++ b/utils/6c/swt.c @@ -96,7 +96,7 @@ swit1(C1 *q, int nc, long def, Node *n) } void -cas(void) +casf(void) { Case *c; diff --git a/utils/8c/gc.h b/utils/8c/gc.h index 4aeb11c0..b6050d82 100644 --- a/utils/8c/gc.h +++ b/utils/8c/gc.h @@ -268,7 +268,7 @@ void gpseudo(int, Sym*, Node*); int swcmp(const void*, const void*); void doswit(Node*); void swit1(C1*, int, long, Node*); -void cas(void); +void casf(void); void bitload(Node*, Node*, Node*, Node*, Node*); void bitstore(Node*, Node*, Node*, Node*, Node*); long outstring(char*, long); diff --git a/utils/8c/sgen.c b/utils/8c/sgen.c index f5fb2090..e6282b21 100644 --- a/utils/8c/sgen.c +++ b/utils/8c/sgen.c @@ -177,7 +177,7 @@ loop: if(cases == C) diag(n, "case/default outside a switch"); if(l == Z) { - cas(); + casf(); cases->val = 0; cases->def = 1; cases->label = pc; @@ -188,7 +188,7 @@ loop: goto rloop; if(l->op == OCONST) if(typechl[l->type->etype]) { - cas(); + casf(); cases->val = l->vconst; cases->def = 0; cases->label = pc; @@ -212,7 +212,7 @@ loop: cn = cases; cases = C; - cas(); + casf(); sbc = breakpc; breakpc = pc; diff --git a/utils/8c/swt.c b/utils/8c/swt.c index 02f3a1de..a29b95c7 100644 --- a/utils/8c/swt.c +++ b/utils/8c/swt.c @@ -89,7 +89,7 @@ swit1(C1 *q, int nc, long def, Node *n) } void -cas(void) +casf(void) { Case *c; diff --git a/utils/9c/9.out.h b/utils/9c/9.out.h new file mode 100644 index 00000000..14feb679 --- /dev/null +++ b/utils/9c/9.out.h @@ -0,0 +1,419 @@ +/* + * powerpc 64 + */ +#define NSNAME 8 +#define NSYM 50 +#define NREG 32 + +#define NOPROF (1<<0) +#define DUPOK (1<<1) + +enum +{ + REGZERO = 0, /* set to zero */ + REGSP = 1, + REGSB = 2, + REGRET = 3, + REGARG = 3, + REGMIN = 7, /* register variables allocated from here to REGMAX */ + REGMAX = 27, + REGEXT = 30, /* external registers allocated from here down */ + REGTMP = 31, /* used by the linker */ + + FREGRET = 0, + FREGMIN = 17, /* first register variable */ + FREGEXT = 26, /* first external register */ + FREGCVI = 27, /* floating conversion constant */ + FREGZERO = 28, /* both float and double */ + FREGHALF = 29, /* double */ + FREGONE = 30, /* double */ + FREGTWO = 31 /* double */ +/* + * GENERAL: + * + * compiler allocates R3 up as temps + * compiler allocates register variables R7-R27 + * compiler allocates external registers R30 down + * + * compiler allocates register variables F17-F26 + * compiler allocates external registers F26 down + */ +}; + +enum as +{ + AXXX = 0, + AADD, + AADDCC, + AADDV, + AADDVCC, + AADDC, + AADDCCC, + AADDCV, + AADDCVCC, + AADDME, + AADDMECC, + AADDMEVCC, + AADDMEV, + AADDE, + AADDECC, + AADDEVCC, + AADDEV, + AADDZE, + AADDZECC, + AADDZEVCC, + AADDZEV, + AAND, + AANDCC, + AANDN, + AANDNCC, + ABC, + ABCL, + ABEQ, + ABGE, + ABGT, + ABL, + ABLE, + ABLT, + ABNE, + ABR, + ABVC, + ABVS, + ACMP, + ACMPU, + ACNTLZW, + ACNTLZWCC, + ACRAND, + ACRANDN, + ACREQV, + ACRNAND, + ACRNOR, + ACROR, + ACRORN, + ACRXOR, + ADIVW, + ADIVWCC, + ADIVWVCC, + ADIVWV, + ADIVWU, + ADIVWUCC, + ADIVWUVCC, + ADIVWUV, + AEQV, + AEQVCC, + AEXTSB, + AEXTSBCC, + AEXTSH, + AEXTSHCC, + AFABS, + AFABSCC, + AFADD, + AFADDCC, + AFADDS, + AFADDSCC, + AFCMPO, + AFCMPU, + AFCTIW, + AFCTIWCC, + AFCTIWZ, + AFCTIWZCC, + AFDIV, + AFDIVCC, + AFDIVS, + AFDIVSCC, + AFMADD, + AFMADDCC, + AFMADDS, + AFMADDSCC, + AFMOVD, + AFMOVDCC, + AFMOVDU, + AFMOVS, + AFMOVSU, + AFMSUB, + AFMSUBCC, + AFMSUBS, + AFMSUBSCC, + AFMUL, + AFMULCC, + AFMULS, + AFMULSCC, + AFNABS, + AFNABSCC, + AFNEG, + AFNEGCC, + AFNMADD, + AFNMADDCC, + AFNMADDS, + AFNMADDSCC, + AFNMSUB, + AFNMSUBCC, + AFNMSUBS, + AFNMSUBSCC, + AFRSP, + AFRSPCC, + AFSUB, + AFSUBCC, + AFSUBS, + AFSUBSCC, + AMOVMW, + ALSW, + ALWAR, + AMOVWBR, + AMOVB, + AMOVBU, + AMOVBZ, + AMOVBZU, + AMOVH, + AMOVHBR, + AMOVHU, + AMOVHZ, + AMOVHZU, + AMOVW, + AMOVWU, + AMOVFL, + AMOVCRFS, + AMTFSB0, + AMTFSB0CC, + AMTFSB1, + AMTFSB1CC, + AMULHW, + AMULHWCC, + AMULHWU, + AMULHWUCC, + AMULLW, + AMULLWCC, + AMULLWVCC, + AMULLWV, + ANAND, + ANANDCC, + ANEG, + ANEGCC, + ANEGVCC, + ANEGV, + ANOR, + ANORCC, + AOR, + AORCC, + AORN, + AORNCC, + AREM, + AREMCC, + AREMV, + AREMVCC, + AREMU, + AREMUCC, + AREMUV, + AREMUVCC, + ARFI, + ARLWMI, + ARLWMICC, + ARLWNM, + ARLWNMCC, + ASLW, + ASLWCC, + ASRW, + ASRAW, + ASRAWCC, + ASRWCC, + ASTSW, + ASTWCCC, + ASUB, + ASUBCC, + ASUBVCC, + ASUBC, + ASUBCCC, + ASUBCV, + ASUBCVCC, + ASUBME, + ASUBMECC, + ASUBMEVCC, + ASUBMEV, + ASUBV, + ASUBE, + ASUBECC, + ASUBEV, + ASUBEVCC, + ASUBZE, + ASUBZECC, + ASUBZEVCC, + ASUBZEV, + ASYNC, + AXOR, + AXORCC, + + ADCBF, + ADCBI, + ADCBST, + ADCBT, + ADCBTST, + ADCBZ, + AECIWX, + AECOWX, + AEIEIO, + AICBI, + AISYNC, + APTESYNC, + ATLBIE, + ATLBIEL, + ATLBSYNC, + ATW, + + ASYSCALL, + ADATA, + AGLOBL, + AGOK, + AHISTORY, + ANAME, + ANOP, + ARETURN, + ATEXT, + AWORD, + AEND, + ADYNT, + AINIT, + ASIGNAME, + + ARFCI, + + /* optional on 32-bit */ + AFRES, + AFRESCC, + AFRSQRTE, + AFRSQRTECC, + AFSEL, + AFSELCC, + AFSQRT, + AFSQRTCC, + AFSQRTS, + AFSQRTSCC, + + /* 64-bit */ + + ACNTLZD, + ACNTLZDCC, + ACMPW, /* CMP with L=0 */ + ACMPWU, + ADIVD, + ADIVDCC, + ADIVDVCC, + ADIVDV, + ADIVDU, + ADIVDUCC, + ADIVDUVCC, + ADIVDUV, + AEXTSW, + AEXTSWCC, + /* AFCFIW; AFCFIWCC */ + AFCFID, + AFCFIDCC, + AFCTID, + AFCTIDCC, + AFCTIDZ, + AFCTIDZCC, + ALDAR, + AMOVD, + AMOVDU, + AMOVWZ, + AMOVWZU, + AMULHD, + AMULHDCC, + AMULHDU, + AMULHDUCC, + AMULLD, + AMULLDCC, + AMULLDVCC, + AMULLDV, + ARFID, + ARLDMI, + ARLDMICC, + ARLDC, + ARLDCCC, + ARLDCR, + ARLDCRCC, + ARLDCL, + ARLDCLCC, + ASLBIA, + ASLBIE, + ASLBMFEE, + ASLBMFEV, + ASLBMTE, + ASLD, + ASLDCC, + ASRD, + ASRAD, + ASRADCC, + ASRDCC, + ASTDCCC, + ATD, + + /* 64-bit pseudo operation */ + ADWORD, + AREMD, + AREMDCC, + AREMDV, + AREMDVCC, + AREMDU, + AREMDUCC, + AREMDUV, + AREMDUVCC, + + /* more 64-bit operations */ + AHRFID, + + ALAST +}; + +/* type/name */ +enum +{ + D_GOK = 0, + D_NONE, + +/* name */ + D_EXTERN, + D_STATIC, + D_AUTO, + D_PARAM, + +/* type */ + D_BRANCH, + D_OREG, + D_CONST, + D_FCONST, + D_SCONST, + D_REG, + D_FPSCR, + D_MSR, + D_FREG, + D_CREG, + D_SPR, + D_OPT, /* branch/trap option */ + D_FILE, + D_FILE1, + D_DCR, /* device control register */ + D_DCONST, + +/* reg names iff type is D_SPR */ + D_XER = 1, + D_LR = 8, + D_CTR = 9 + /* and many supervisor level registers */ +}; + +/* + * this is the ranlib header + */ +#define SYMDEF "__.SYMDEF" + +/* + * this is the simulated IEEE floating point + */ +typedef struct ieee Ieee; +struct ieee +{ + long l; /* contains ls-man 0xffffffff */ + long h; /* contains sign 0x80000000 + exp 0x7ff00000 + ms-man 0x000fffff */ +}; diff --git a/utils/acid/acid.h b/utils/acid/acid.h index 68c8913d..cb88a554 100644 --- a/utils/acid/acid.h +++ b/utils/acid/acid.h @@ -240,7 +240,7 @@ int remote_read(int, char*, int); int remote_write(int, char*, int); int remput(struct segment*, ulong, long, char*, int); void restartio(void); -vlong rget(Map*, char*); +uvlong rget(Map*, char*); String *runenode(Rune*); char* runcmd(char*); int scmp(String*, String*); @@ -251,7 +251,7 @@ String* stradd(String*, String*); String* strnode(char*); String* strnodlen(char*, int); char* mysystem(void); -void trlist(Map*, ulong, ulong, Symbol*); +void trlist(Map*, uvlong, uvlong, Symbol*); void unwind(void); void userinit(void); void varreg(void); diff --git a/utils/acid/builtin.c b/utils/acid/builtin.c index 2afc447b..56c4dceb 100644 --- a/utils/acid/builtin.c +++ b/utils/acid/builtin.c @@ -342,7 +342,7 @@ follow(Node *r, Node *args) { int n, i; Node res; - ulong f[10]; + uvlong f[10]; List **tail, *l; if(args == 0) @@ -369,7 +369,7 @@ funcbound(Node *r, Node *args) { int n; Node res; - ulong bounds[2]; + uvlong bounds[2]; List *l; if(args == 0) diff --git a/utils/acid/exec.c b/utils/acid/exec.c index d110673b..f77eddc2 100644 --- a/utils/acid/exec.c +++ b/utils/acid/exec.c @@ -210,8 +210,8 @@ void indir(Map *m, ulong addr, char fmt, Node *r) { int i; - long ival; - vlong vval; + ulong ival; + uvlong vval; int ret; uchar cval; ushort sval; diff --git a/utils/acid/expr.c b/utils/acid/expr.c index da413742..4d3dcd94 100644 --- a/utils/acid/expr.c +++ b/utils/acid/expr.c @@ -153,7 +153,7 @@ oframe(Node *n, Node *res) { char *p; Node *lp; - long ival; + uvlong ival; Frtype *f; p = n->sym->name; diff --git a/utils/acid/list.c b/utils/acid/list.c index ced2f4d8..b85760ee 100644 --- a/utils/acid/list.c +++ b/utils/acid/list.c @@ -194,7 +194,7 @@ static List* listlocals(Map *map, Symbol *fn, ulong fp) { int i; - long val; + uvlong val; Symbol s; List **tail, *l2; @@ -208,7 +208,7 @@ listlocals(Map *map, Symbol *fn, ulong fp) if(s.name[0] == '.') continue; - if(get4(map, fp-s.value, &val) > 0) { + if(geta(map, fp-s.value, &val) > 0) { *tail = listvar(s.name, val); tail = &(*tail)->next; } @@ -221,7 +221,7 @@ listparams(Map *map, Symbol *fn, ulong fp) { int i; Symbol s; - long v; + uvlong v; List **tail, *l2; l2 = 0; @@ -232,7 +232,7 @@ listparams(Map *map, Symbol *fn, ulong fp) if (s.class != CPARAM) continue; - if(get4(map, fp+s.value, &v) > 0) { + if(geta(map, fp+s.value, &v) > 0) { *tail = listvar(s.name, v); tail = &(*tail)->next; } @@ -241,7 +241,7 @@ listparams(Map *map, Symbol *fn, ulong fp) } void -trlist(Map *map, ulong pc, ulong sp, Symbol *sym) +trlist(Map *map, uvlong pc, uvlong sp, Symbol *sym) { List *q, *l; diff --git a/utils/acid/main.c b/utils/acid/main.c index 5bd85f13..bf4ad240 100644 --- a/utils/acid/main.c +++ b/utils/acid/main.c @@ -196,8 +196,7 @@ main(int argc, char *argv[]) unwind(); } - Bputc(bout, '\n'); - exits(0); + /* not reached */ } static int diff --git a/utils/acid/os-Plan9.c b/utils/acid/os-Plan9.c index 1ac60404..8fcfa141 100644 --- a/utils/acid/os-Plan9.c +++ b/utils/acid/os-Plan9.c @@ -54,7 +54,7 @@ waitfor(int pid) } free(w); } - return nil; + /* not reached */ } char * @@ -78,7 +78,7 @@ runcmd(char *cmd) default: return waitfor(pid); } - return 0; + /* not reached */ } void diff --git a/utils/acid/util.c b/utils/acid/util.c index 0de244fd..fc3d31e9 100644 --- a/utils/acid/util.c +++ b/utils/acid/util.c @@ -35,7 +35,7 @@ unique(char *buf, Sym *s) } } if(renamed && !quiet) - print("\t%s=%s %c/%lux\n", s->name, buf, s->type, s->value); + print("\t%s=%s %c/%llux\n", s->name, buf, s->type, s->value); if(l == 0) l = enter(buf, Tid); return l; @@ -193,12 +193,12 @@ loadvars(void) } } -vlong +uvlong rget(Map *map, char *reg) { Lsym *s; - long x; - vlong v; + ulong x; + uvlong v; int ret; s = look(reg); @@ -206,7 +206,7 @@ rget(Map *map, char *reg) fatal("rget: %s\n", reg); if(s->v->vstore.fmt == 'Y') - ret = get8(map, (long)s->v->vstore.u0.sival, &v); + ret = get8(map, s->v->vstore.u0.sival, &v); else { ret = get4(map, (long)s->v->vstore.u0.sival, &x); v = x; diff --git a/utils/c2l/com.c b/utils/c2l/com.c index 283c2ae9..e40bfa2a 100644 --- a/utils/c2l/com.c +++ b/utils/c2l/com.c @@ -599,6 +599,7 @@ addaddr: if(n->type->etype == TARRAY) n->type = typ1(TIND, n->type->link); return 0; +#ifdef WHATEVA if(tlvalue(n)) goto bad; l = new1(OXXX, Z, Z); @@ -611,6 +612,7 @@ addaddr: n->type = typ1(TIND, l->type); n->type->width = types[TIND]->width; return 0; +#endif bad: n->type = T; diff --git a/utils/c2l/dcl.c b/utils/c2l/dcl.c index 6fb6977a..1f576467 100644 --- a/utils/c2l/dcl.c +++ b/utils/c2l/dcl.c @@ -926,7 +926,7 @@ rsametype(Type *t1, Type *t2, int n, int f) return 1; } } - return 0; + /* not reached */ } ulong diff --git a/utils/c2l/lex.c b/utils/c2l/lex.c index 5701dd99..574ecfc6 100644 --- a/utils/c2l/lex.c +++ b/utils/c2l/lex.c @@ -951,7 +951,7 @@ getnsc(void) } c = GETC(); } - return 0; + /* not reached */ } void diff --git a/utils/c2l/sub.c b/utils/c2l/sub.c index a696cb0f..4c0f2cdb 100644 --- a/utils/c2l/sub.c +++ b/utils/c2l/sub.c @@ -263,10 +263,12 @@ simplet(long b) int stcompat(Node *n, Type *t1, Type *t2, long ttab[]) { + USED(n); USED(t1); USED(t2); USED(ttab[0]); + return 0; +#ifdef WHATEVA int i; ulong b; - return 0; i = 0; if(t2 != T) i = t2->etype; @@ -286,6 +288,7 @@ stcompat(Node *n, Type *t1, Type *t2, long ttab[]) return 0; } return 1; +#endif } int diff --git a/utils/cc/cc.h b/utils/cc/cc.h index d05b4397..2813d25f 100644 --- a/utils/cc/cc.h +++ b/utils/cc/cc.h @@ -121,7 +121,7 @@ struct Type long width; long offset; long lineno; - char shift; + schar shift; char nbits; char etype; char garb; @@ -317,6 +317,7 @@ enum TSTRUCT, TUNION, TENUM, + TDOT, NTYPE, TAUTO = NTYPE, @@ -329,7 +330,6 @@ enum TVOLATILE, TUNSIGNED, TSIGNED, - TDOT, TFILE, TOLD, NALLTYPES, @@ -430,6 +430,7 @@ EXTERN Type* firstargtype; EXTERN Decl* firstdcl; EXTERN int fperror; EXTERN Sym* hash[NHASH]; +EXTERN int hasdoubled; EXTERN char* hunk; EXTERN char* include[20]; EXTERN Io* iofree; @@ -473,6 +474,9 @@ EXTERN int nterm; EXTERN int packflg; EXTERN int fproundflg; EXTERN int profileflg; +EXTERN int ncontin; +EXTERN int canreach; +EXTERN int warnreach; EXTERN Bits zbits; extern char *onames[], *tnames[], *gnames[]; @@ -501,6 +505,9 @@ extern char typechlvp[]; extern char typechlp[]; extern char typechlpfd[]; +EXTERN char* typeword; +EXTERN char* typecmplx; + extern ulong thash1; extern ulong thash2; extern ulong thash3; @@ -596,7 +603,7 @@ void edecl(int, Type*, Sym*); Type* fnproto(Node*); Type* fnproto1(Node*); void markdcl(void); -Type* paramconv(Type*, int); +Type* paramconv(Type*, int, int); void pdecl(int, Type*, Sym*); Decl* push(void); Decl* push1(Sym*); diff --git a/utils/cc/com.c b/utils/cc/com.c index 558077b7..59a7bd06 100644 --- a/utils/cc/com.c +++ b/utils/cc/com.c @@ -221,6 +221,8 @@ tcomo(Node *n, int f) if(tcompat(n, l->type, r->type, tand)) goto bad; n->type = l->type; + n->right = new1(OCAST, r, Z); + n->right->type = types[TINT]; if(typeu[n->type->etype]) { if(n->op == OASASHR) n->op = OASLSHR; diff --git a/utils/cc/com64.c b/utils/cc/com64.c index 88bf11bf..e1f7c8a3 100644 --- a/utils/cc/com64.c +++ b/utils/cc/com64.c @@ -1,7 +1,7 @@ #include "cc.h" /* - * this is machine depend, but it is totally + * this is machine dependent, but it is totally * common on all of the 64-bit symulating machines. */ @@ -258,6 +258,8 @@ com64(Node *n) r->op = OFUNC; r->type = types[TLONG]; return 1; + case OCOND: + return 1; } } @@ -503,6 +505,7 @@ setvinc: n->left = a; l = new(OADDR, l, Z); l->type = typ(TIND, l->left->type); + l->complex = l->left->complex; n->right = new(OLIST, l, r); n->complex = FNX; n->op = OFUNC; @@ -536,6 +539,7 @@ setasop: t = new(OADDR, l, 0); t->type = typ(TIND, l->type); + t->complex = l->complex; r = new(OLIST, t, r); n->left = nodvasop; @@ -551,6 +555,8 @@ bool64(Node *n) { Node *n1; + if(machcap(Z)) + return; if(typev[n->type->etype]) { n1 = new(OXXX, 0, 0); *n1 = *n; diff --git a/utils/cc/dcl.c b/utils/cc/dcl.c index 71925701..6a8e7245 100644 --- a/utils/cc/dcl.c +++ b/utils/cc/dcl.c @@ -347,6 +347,10 @@ init1(Sym *s, Type *t, long o, int exflag) return Z; if(a->op == OCONST) { + if(vconst(a) && t->etype == TIND && a->type && a->type->etype != TIND){ + diag(a, "initialize pointer to an integer: %s", s->name); + return Z; + } if(!sametype(a->type, t)) { /* hoop jumping to save malloc */ if(nodcast == Z) @@ -537,6 +541,7 @@ suallign(Type *t) l->offset = o; } else { if(l->width <= 0) + if(l->down != T) if(l->sym) diag(Z, "incomplete structure element: %s", l->sym->name); @@ -864,7 +869,7 @@ fnproto1(Node *n) dodecl(NODECL, CXXX, n->type, n->left); t = typ(TXXX, T); if(lastdcl != T) - *t = *paramconv(lastdcl, 1); + *t = *paramconv(lastdcl, 1, 0); return t; case ONAME: @@ -970,6 +975,12 @@ rsametype(Type *t1, Type *t2, int n, int f) snap(t1); if(t2->link == T) snap(t2); + if(t1 != t2 && t1->link == T && t2->link == T){ + /* structs with missing or different tag names aren't considered equal */ + if(t1->tag == nil || t2->tag == nil || + strcmp(t1->tag->name, t2->tag->name) != 0) + return 0; + } t1 = t1->link; t2 = t2->link; for(;;) { @@ -990,7 +1001,6 @@ rsametype(Type *t1, Type *t2, int n, int f) return 1; } } - return 0; } typedef struct Typetab Typetab; @@ -1166,13 +1176,13 @@ dcllabel(Sym *s, int f) } Type* -paramconv(Type *t, int f) +paramconv(Type *t, int f, int defining) { switch(t->etype) { case TUNION: case TSTRUCT: - if(t->width <= 0) + if(t->width <= 0 && defining) diag(Z, "incomplete structure: %s", t->tag->name); break; @@ -1266,7 +1276,7 @@ pdecl(int c, Type *t, Sym *s) diag(Z, "not a parameter: %s", s->name); return; } - t = paramconv(t, c==CPARAM); + t = paramconv(t, c==CPARAM, 1); if(c == CXXX) c = CPARAM; if(c != CPARAM) { diff --git a/utils/cc/dpchk.c b/utils/cc/dpchk.c index a061b12c..011f9c8a 100644 --- a/utils/cc/dpchk.c +++ b/utils/cc/dpchk.c @@ -158,6 +158,7 @@ arginit(void) argflag('.', Fignor); argflag('#', Fignor); argflag('u', Fignor); + argflag('h', Fignor); argflag('+', Fignor); argflag('-', Fignor); @@ -444,18 +445,48 @@ void pragincomplete(void) { Sym *s; + Type *t; + int istag, w, et; + istag = 0; s = getsym(); - if(s){ - if(strcmp(s->name, "_off_") == 0) - debug['T'] = 0; - else if(strcmp(s->name, "_on_") == 0) - debug['T'] = 1; - else if(s->type == T) - diag(Z, "unknown type %s in pragma incomplete", s->name); - else - s->type->garb |= GINCOMPLETE; + if(s == nil) + goto out; + et = 0; + w = s->lexical; + if(w == LSTRUCT) + et = TSTRUCT; + else if(w == LUNION) + et = TUNION; + if(et != 0){ + s = getsym(); + if(s == nil){ + yyerror("missing struct/union tag in pragma incomplete"); + goto out; + } + if(s->lexical != LNAME && s->lexical != LTYPE){ + yyerror("invalid struct/union tag: %s", s->name); + goto out; + } + dotag(s, et, 0); + istag = 1; + }else if(strcmp(s->name, "_off_") == 0){ + debug['T'] = 0; + goto out; + }else if(strcmp(s->name, "_on_") == 0){ + debug['T'] = 1; + goto out; } + t = s->type; + if(istag) + t = s->suetag; + if(t == T) + yyerror("unknown type %s in pragma incomplete", s->name); + else if(!typesu[t->etype]) + yyerror("not struct/union type in pragma incomplete: %s", s->name); + else + t->garb |= GINCOMPLETE; +out: while(getnsc() != '\n') ; if(debug['f']) diff --git a/utils/cc/lex.c b/utils/cc/lex.c index 7a99164b..8e96b7bb 100644 --- a/utils/cc/lex.c +++ b/utils/cc/lex.c @@ -7,27 +7,30 @@ /* * known debug flags - * -o file output file - * -D name define - * -I path include * -a acid declaration output - * -M constant multiplication - * -B non ANSI * -A !B + * -B non ANSI * -d print declarations - * -t print type trees - * -L print every NAME symbol - * -i print initialization + * -D name define * -F format specification check - * -r print registerization - * -v verbose printing - * -X abort on error - * -w print warnings + * -i print initialization + * -I path include + * -l generate little-endian code + * -L print every NAME symbol + * -M constant multiplication * -m print add/sub/mul trees - * -s print structure offsets (with -a or -aa) * -n print acid to file (%.c=%.acid) (with -a or -aa) + * -o file output file * -p use standard cpp ANSI preprocessor (not on windows) + * -r print registerization + * -s print structure offsets (with -a or -aa) + * -S print assembly + * -t print type trees * -V enable void* conversion warnings + * -v verbose printing + * -w print warnings + * -X abort on error + * -. Inhibit search for includes in source directory */ void @@ -54,6 +57,15 @@ main(int argc, char *argv[]) debug[c]++; break; + case 'l': /* for little-endian mips */ + if(thechar != 'v'){ + print("can only use -l with vc"); + errorexit(); + } + thechar = '0'; + thestring = "spim"; + break; + case 'o': outfile = ARGF(); break; @@ -81,7 +93,12 @@ main(int argc, char *argv[]) } if(argc > 1 && !systemtype(Windows)) { nproc = 1; - if(p = getenv("NPROC")) + /* + * if we're writing acid to standard output, don't compile + * concurrently, to avoid interleaving output. + */ + if(((!debug['a'] && !debug['Z']) || debug['n']) && + (p = getenv("NPROC")) != nil) nproc = atol(p); /* */ c = 0; nout = 0; @@ -137,6 +154,7 @@ compile(char *file, char **defs, int ndef) char ofile[400], incfile[20]; char *p, *av[100], opt[256]; int i, c, fd[2]; + static int first = 1; strcpy(ofile, file); p = utfrrune(ofile, pathchar()); @@ -146,6 +164,7 @@ compile(char *file, char **defs, int ndef) include[0] = strdup(ofile); } else p = ofile; + if(outfile == 0) { outfile = p; if(outfile) { @@ -175,21 +194,29 @@ compile(char *file, char **defs, int ndef) setinclude("/sys/include"); } } + if (first) + Binit(&diagbuf, 1, OWRITE); + /* + * if we're writing acid to standard output, don't keep scratching + * outbuf. + */ if((debug['a'] || debug['Z']) && !debug['n']) { - outfile = 0; - Binit(&outbuf, 1, OWRITE); - Binit(&diagbuf, 2, OWRITE); + if (first) { + outfile = 0; + Binit(&outbuf, dup(1, -1), OWRITE); + dup(2, 1); + } } else { c = mycreat(outfile, 0664); if(c < 0) { - diag(Z, "cannot open %s", outfile); + diag(Z, "cannot open %s - %r", outfile); outfile = 0; errorexit(); } Binit(&outbuf, c, OWRITE); - Binit(&diagbuf, 1, OWRITE); } newio(); + first = 0; /* Use an ANSI preprocessor */ if(debug['p']) { @@ -215,6 +242,10 @@ compile(char *file, char **defs, int ndef) close(fd[1]); av[0] = CPP; i = 1; + if(debug['.']){ + sprint(opt, "-."); + av[i++] = strdup(opt); + } if(debug['+']) { sprint(opt, "-+"); av[i++] = strdup(opt); @@ -1005,7 +1036,6 @@ getnsc(void) } c = GETC(); } - return 0; } void @@ -1123,9 +1153,11 @@ struct "for", LFOR, 0, "goto", LGOTO, 0, "if", LIF, 0, + "inline", LINLINE, 0, "int", LINT, TINT, "long", LLONG, TLONG, "register", LREGISTER, 0, + "restrict", LRESTRICT, 0, "return", LRETURN, 0, "SET", LSET, 0, "short", LSHORT, TSHORT, diff --git a/utils/cc/lexbody b/utils/cc/lexbody index d8e3f6eb..6b226ada 100644 --- a/utils/cc/lexbody +++ b/utils/cc/lexbody @@ -417,10 +417,8 @@ l1: if(c1 == '/') { for(;;) { c = GETC(); - if(c == '\n') { - lineno++; - goto l0; - } + if(c == '\n') + goto l1; if(c == EOF) { yyerror("eof in comment"); errorexit(); diff --git a/utils/cc/mkfile b/utils/cc/mkfile index c2df13a5..9a5036be 100644 --- a/utils/cc/mkfile +++ b/utils/cc/mkfile @@ -18,7 +18,7 @@ OFILES=\ scon.$O\ sub.$O\ y.tab.$O\ - machcap.$O\ + omachcap.$O\ HFILES=cc.h\ y.tab.h\ diff --git a/utils/cc/pgen.c b/utils/cc/pgen.c new file mode 100644 index 00000000..131ff012 --- /dev/null +++ b/utils/cc/pgen.c @@ -0,0 +1,548 @@ +#include "gc.h" + +void +codgen(Node *n, Node *nn) +{ + Prog *sp; + Node *n1, nod, nod1; + + cursafe = 0; + curarg = 0; + maxargsafe = 0; + hasdoubled = 0; + + /* + * isolate name + */ + for(n1 = nn;; n1 = n1->left) { + if(n1 == Z) { + diag(nn, "cant find function name"); + return; + } + if(n1->op == ONAME) + break; + } + nearln = nn->lineno; + gpseudo(ATEXT, n1->sym, nodconst(stkoff)); + sp = p; + + if(typecmplx[thisfn->link->etype]) { + if(nodret == nil) { + nodret = new(ONAME, Z, Z); + nodret->sym = slookup(".ret"); + nodret->class = CPARAM; + nodret->type = types[TIND]; + nodret->etype = TIND; + nodret = new(OIND, nodret, Z); + } + n1 = nodret->left; + if(n1->type == T || n1->type->link != thisfn->link) { + n1->type = typ(TIND, thisfn->link); + n1->etype = n1->type->etype; + nodret = new(OIND, n1, Z); + complex(nodret); + } + } + + /* + * isolate first argument + */ + if(REGARG >= 0) { + if(typecmplx[thisfn->link->etype]) { + nod1 = *nodret->left; + nodreg(&nod, &nod1, REGARG); + gmove(&nod, &nod1); + } else + if(firstarg && typeword[firstargtype->etype]) { + nod1 = znode; + nod1.op = ONAME; + nod1.sym = firstarg; + nod1.type = firstargtype; + nod1.class = CPARAM; + nod1.xoffset = align(0, firstargtype, Aarg1); + nod1.etype = firstargtype->etype; + xcom(&nod1); + nodreg(&nod, &nod1, REGARG); + gmove(&nod, &nod1); + } + } + + canreach = 1; + warnreach = 1; + gen(n); + if(canreach && thisfn->link->etype != TVOID) + warn(Z, "no return at end of function: %s", n1->sym->name); + noretval(3); + gbranch(ORETURN); + + if(!debug['N'] || debug['R'] || debug['P']) + regopt(sp); + + if(thechar=='6' || thechar=='7' || thechar=='9' || hasdoubled) /* [sic] */ + maxargsafe = round(maxargsafe, 8); + sp->to.offset += maxargsafe; +} + +void +supgen(Node *n) +{ + int owarn; + long spc; + Prog *sp; + + if(n == Z) + return; + suppress++; + owarn = warnreach; + warnreach = 0; + spc = pc; + sp = lastp; + gen(n); + lastp = sp; + pc = spc; + sp->link = nil; + suppress--; + warnreach = owarn; +} + +void +gen(Node *n) +{ + Node *l, nod; + Prog *sp, *spc, *spb; + Case *cn; + long sbc, scc; + int snbreak, sncontin; + int f, o, oldreach; + +loop: + if(n == Z) + return; + nearln = n->lineno; + o = n->op; + if(debug['G']) + if(o != OLIST) + print("%L %O\n", nearln, o); + + if(!canreach) { + switch(o) { + case OLABEL: + case OCASE: + case OLIST: + case OBREAK: + case OFOR: + case OWHILE: + case ODWHILE: + /* all handled specially - see switch body below */ + break; + default: + if(warnreach) { + warn(n, "unreachable code %O", o); + warnreach = 0; + } + } + } + + switch(o) { + + default: + complex(n); + cgen(n, Z); + break; + + case OLIST: + gen(n->left); + + rloop: + n = n->right; + goto loop; + + case ORETURN: + canreach = 0; + warnreach = !suppress; + complex(n); + if(n->type == T) + break; + l = n->left; + if(l == Z) { + noretval(3); + gbranch(ORETURN); + break; + } + if(typecmplx[n->type->etype]) { + nod = znode; + nod.op = OAS; + nod.left = nodret; + nod.right = l; + nod.type = n->type; + nod.complex = l->complex; + cgen(&nod, Z); + noretval(3); + gbranch(ORETURN); + break; + } + regret(&nod, n); + cgen(l, &nod); + regfree(&nod); + if(typefd[n->type->etype]) + noretval(1); + else + noretval(2); + gbranch(ORETURN); + break; + + case OLABEL: + canreach = 1; + l = n->left; + if(l) { + l->pc = pc; + if(l->label) + patch(l->label, pc); + } + gbranch(OGOTO); /* prevent self reference in reg */ + patch(p, pc); + goto rloop; + + case OGOTO: + canreach = 0; + warnreach = !suppress; + n = n->left; + if(n == Z) + return; + if(n->complex == 0) { + diag(Z, "label undefined: %s", n->sym->name); + return; + } + if(suppress) + return; + gbranch(OGOTO); + if(n->pc) { + patch(p, n->pc); + return; + } + if(n->label) + patch(n->label, pc-1); + n->label = p; + return; + + case OCASE: + canreach = 1; + l = n->left; + if(cases == C) + diag(n, "case/default outside a switch"); + if(l == Z) { + casf(); + cases->val = 0; + cases->def = 1; + cases->label = pc; + cases->isv = 0; + goto rloop; + } + complex(l); + if(l->type == T) + goto rloop; + if(l->op == OCONST) + if(typeword[l->type->etype] && l->type->etype != TIND) { + casf(); + cases->val = l->vconst; + cases->def = 0; + cases->label = pc; + cases->isv = typev[l->type->etype]; + goto rloop; + } + diag(n, "case expression must be integer constant"); + goto rloop; + + case OSWITCH: + l = n->left; + complex(l); + if(l->type == T) + break; + if(!typeword[l->type->etype] || l->type->etype == TIND) { + diag(n, "switch expression must be integer"); + break; + } + + gbranch(OGOTO); /* entry */ + sp = p; + + cn = cases; + cases = C; + casf(); + + sbc = breakpc; + breakpc = pc; + snbreak = nbreak; + nbreak = 0; + gbranch(OGOTO); + spb = p; + + gen(n->right); /* body */ + if(canreach){ + gbranch(OGOTO); + patch(p, breakpc); + nbreak++; + } + + patch(sp, pc); + regalloc(&nod, l, Z); + /* always signed */ + if(typev[l->type->etype]) + nod.type = types[TVLONG]; + else + nod.type = types[TLONG]; + cgen(l, &nod); + doswit(&nod); + regfree(&nod); + patch(spb, pc); + + cases = cn; + breakpc = sbc; + canreach = nbreak!=0; + if(canreach == 0) + warnreach = !suppress; + nbreak = snbreak; + break; + + case OWHILE: + case ODWHILE: + l = n->left; + gbranch(OGOTO); /* entry */ + sp = p; + + scc = continpc; + continpc = pc; + gbranch(OGOTO); + spc = p; + + sbc = breakpc; + breakpc = pc; + snbreak = nbreak; + nbreak = 0; + gbranch(OGOTO); + spb = p; + + patch(spc, pc); + if(n->op == OWHILE) + patch(sp, pc); + bcomplex(l, Z); /* test */ + patch(p, breakpc); + if(l->op != OCONST || vconst(l) == 0) + nbreak++; + + if(n->op == ODWHILE) + patch(sp, pc); + gen(n->right); /* body */ + gbranch(OGOTO); + patch(p, continpc); + + patch(spb, pc); + continpc = scc; + breakpc = sbc; + canreach = nbreak!=0; + if(canreach == 0) + warnreach = !suppress; + nbreak = snbreak; + break; + + case OFOR: + l = n->left; + if(!canreach && l->right->left && warnreach) { + warn(n, "unreachable code FOR"); + warnreach = 0; + } + gen(l->right->left); /* init */ + gbranch(OGOTO); /* entry */ + sp = p; + + /* + * if there are no incoming labels in the + * body and the top's not reachable, warn + */ + if(!canreach && warnreach && deadheads(n)) { + warn(n, "unreachable code %O", o); + warnreach = 0; + } + + scc = continpc; + continpc = pc; + gbranch(OGOTO); + spc = p; + + sbc = breakpc; + breakpc = pc; + snbreak = nbreak; + nbreak = 0; + sncontin = ncontin; + ncontin = 0; + gbranch(OGOTO); + spb = p; + + patch(spc, pc); + gen(l->right->right); /* inc */ + patch(sp, pc); + if(l->left != Z) { /* test */ + bcomplex(l->left, Z); + patch(p, breakpc); + if(l->left->op != OCONST || vconst(l->left) == 0) + nbreak++; + } + canreach = 1; + gen(n->right); /* body */ + if(canreach){ + gbranch(OGOTO); + patch(p, continpc); + ncontin++; + } + if(!ncontin && l->right->right && warnreach) { + warn(l->right->right, "unreachable FOR inc"); + warnreach = 0; + } + + patch(spb, pc); + continpc = scc; + breakpc = sbc; + canreach = nbreak!=0; + if(canreach == 0) + warnreach = !suppress; + nbreak = snbreak; + ncontin = sncontin; + break; + + case OCONTINUE: + if(continpc < 0) { + diag(n, "continue not in a loop"); + break; + } + gbranch(OGOTO); + patch(p, continpc); + ncontin++; + canreach = 0; + warnreach = !suppress; + break; + + case OBREAK: + if(breakpc < 0) { + diag(n, "break not in a loop"); + break; + } + /* + * Don't complain about unreachable break statements. + * There are breaks hidden in yacc's output and some people + * write return; break; in their switch statements out of habit. + * However, don't confuse the analysis by inserting an + * unreachable reference to breakpc either. + */ + if(!canreach) + break; + gbranch(OGOTO); + patch(p, breakpc); + nbreak++; + canreach = 0; + warnreach = !suppress; + break; + + case OIF: + l = n->left; + if(bcomplex(l, n->right)) { + if(typefd[l->type->etype]) + f = !l->fconst; + else + f = !l->vconst; + if(debug['c']) + print("%L const if %s\n", nearln, f ? "false" : "true"); + if(f) { + canreach = 1; + supgen(n->right->left); + oldreach = canreach; + canreach = 1; + gen(n->right->right); + /* + * treat constant ifs as regular ifs for + * reachability warnings. + */ + if(!canreach && oldreach && debug['w'] < 2) + warnreach = 0; + } + else { + canreach = 1; + gen(n->right->left); + oldreach = canreach; + canreach = 1; + supgen(n->right->right); + /* + * treat constant ifs as regular ifs for + * reachability warnings. + */ + if(!oldreach && canreach && debug['w'] < 2) + warnreach = 0; + canreach = oldreach; + } + } + else { + sp = p; + canreach = 1; + if(n->right->left != Z) + gen(n->right->left); + oldreach = canreach; + canreach = 1; + if(n->right->right != Z) { + gbranch(OGOTO); + patch(sp, pc); + sp = p; + gen(n->right->right); + } + patch(sp, pc); + canreach = canreach || oldreach; + if(canreach == 0) + warnreach = !suppress; + } + break; + + case OSET: + case OUSED: + usedset(n->left, o); + break; + } +} + +void +usedset(Node *n, int o) +{ + if(n->op == OLIST) { + usedset(n->left, o); + usedset(n->right, o); + return; + } + complex(n); + switch(n->op) { + case OADDR: /* volatile */ + gins(ANOP, n, Z); + break; + case ONAME: + if(o == OSET) + gins(ANOP, Z, n); + else + gins(ANOP, n, Z); + break; + } +} + +int +bcomplex(Node *n, Node *c) +{ + + complex(n); + if(n->type != T) + if(tcompat(n, T, n->type, tnot)) + n->type = T; + if(n->type == T) { + gbranch(OGOTO); + return 0; + } + if(c != Z && n->op == OCONST && deadheads(c)) + return 1; + bool64(n); + boolgen(n, 1, Z); + return 0; +} diff --git a/utils/cc/pickle.c b/utils/cc/pickle.c index 370b9983..ef8df4c0 100644 --- a/utils/cc/pickle.c +++ b/utils/cc/pickle.c @@ -195,7 +195,7 @@ pickletype(Type *t) goto asmstr; an = pmap(s->name); - Bprint(&outbuf, "char *\npickle_%s(char *bp, char *ep, int un, %s *addr)\n{\n\tint _i = 0;\n\n\tUSED(_i);\n", an, an); + Bprint(&outbuf, "uchar*\npickle_%s(uchar *bp, uchar *ep, int un, %s *addr)\n{\n\tint _i = 0;\n\n\tUSED(_i);\n", an, an); for(l = t->link; l != T; l = l->down) picklemember(l, 0); Bprint(&outbuf, "\treturn bp;\n}\n\n"); diff --git a/utils/cc/pswt.c b/utils/cc/pswt.c new file mode 100644 index 00000000..6ef4f2fb --- /dev/null +++ b/utils/cc/pswt.c @@ -0,0 +1,144 @@ +#include "gc.h" + +int +swcmp(const void *a1, const void *a2) +{ + C1 *p1, *p2; + + p1 = (C1*)a1; + p2 = (C1*)a2; + if(p1->val < p2->val) + return -1; + return p1->val > p2->val; +} + +void +doswit(Node *n) +{ + Case *c; + C1 *q, *iq; + long def, nc, i, isv; + int dup; + + def = 0; + nc = 0; + isv = 0; + for(c = cases; c->link != C; c = c->link) { + if(c->def) { + if(def) + diag(n, "more than one default in switch"); + def = c->label; + continue; + } + isv |= c->isv; + nc++; + } + if(isv && !typev[n->type->etype]) + warn(n, "32-bit switch expression with 64-bit case constant"); + + iq = alloc(nc*sizeof(C1)); + q = iq; + for(c = cases; c->link != C; c = c->link) { + if(c->def) + continue; + q->label = c->label; + if(isv) + q->val = c->val; + else + q->val = (long)c->val; /* cast ensures correct value for 32-bit switch on 64-bit architecture */ + q++; + } + qsort(iq, nc, sizeof(C1), swcmp); + if(debug['W']) + for(i=0; i<nc; i++) + print("case %2ld: = %.8llux\n", i, (vlong)iq[i].val); + dup = 0; + for(i=0; i<nc-1; i++) + if(iq[i].val == iq[i+1].val) { + diag(n, "duplicate cases in switch %lld", (vlong)iq[i].val); + dup = 1; + } + if(dup) + return; + if(def == 0) { + def = breakpc; + nbreak++; + } + swit1(iq, nc, def, n); +} + +void +casf(void) +{ + Case *c; + + c = alloc(sizeof(*c)); + c->link = cases; + cases = c; +} + +long +outlstring(ushort *s, long n) +{ + char buf[2]; + int c; + long r; + + if(suppress) + return nstring; + while(nstring & 1) + outstring("", 1); + r = nstring; + while(n > 0) { + c = *s++; + if(align(0, types[TCHAR], Aarg1)) { + buf[0] = c>>8; + buf[1] = c; + } else { + buf[0] = c; + buf[1] = c>>8; + } + outstring(buf, 2); + n -= sizeof(ushort); + } + return r; +} + +void +nullwarn(Node *l, Node *r) +{ + warn(Z, "result of operation not used"); + if(l != Z) + cgen(l, Z); + if(r != Z) + cgen(r, Z); +} + +void +ieeedtod(Ieee *ieee, double native) +{ + double fr, ho, f; + int exp; + + if(native < 0) { + ieeedtod(ieee, -native); + ieee->h |= 0x80000000L; + return; + } + if(native == 0) { + ieee->l = 0; + ieee->h = 0; + return; + } + fr = frexp(native, &exp); + f = 2097152L; /* shouldnt use fp constants here */ + fr = modf(fr*f, &ho); + ieee->h = ho; + ieee->h &= 0xfffffL; + ieee->h |= (exp+1022L) << 20; + f = 65536L; + fr = modf(fr*f, &ho); + ieee->l = ho; + ieee->l <<= 16; + ieee->l |= (long)(fr*f); +} diff --git a/utils/ftl/ftl.c b/utils/ftl/ftl.c index 231f1ae5..2f8a1e1b 100644 --- a/utils/ftl/ftl.c +++ b/utils/ftl/ftl.c @@ -209,7 +209,7 @@ ftlread(void *buf, long n, ulong offset) a += Bsize; } return a-(uchar*)buf; - return 0; /* not reached */ + /* not reached */ } static long @@ -256,7 +256,7 @@ ftlwrite(void *buf, long n, ulong offset) a += Bsize; } return a-(uchar*)buf; - return 0; /* not reached */ + /* not reached */ } static Ftl * diff --git a/utils/include/a.out.h b/utils/include/a.out.h index 8c0b7137..59077860 100644 --- a/utils/include/a.out.h +++ b/utils/include/a.out.h @@ -11,7 +11,6 @@ struct Exec long pcsz; /* size of pc/line number table */ }; - #define HDR_MAGIC 0x00008000 /* header expansion */ #define _MAGIC(f, b) ((f)|((((4*(b))+0)*(b))+7)) @@ -30,16 +29,18 @@ struct Exec #define P_MAGIC _MAGIC(0, 24) /* mips 3000 LE */ #define U_MAGIC _MAGIC(0, 25) /* sparc64 */ #define S_MAGIC _MAGIC(HDR_MAGIC, 26) /* amd64 */ +#define T_MAGIC _MAGIC(HDR_MAGIC, 27) /* powerpc64 */ #define MIN_MAGIC 8 -#define MAX_MAGIC 26 /* <= 90 */ +#define MAX_MAGIC 27 /* <= 90 */ -#define DYN_MAGIC 0x80000000 /* or'd in for dynamically loaded modules */ +#define DYN_MAGIC 0x80000000 /* dlm */ typedef struct Sym Sym; struct Sym { - long value; + vlong value; + uint sig; char type; char *name; }; diff --git a/utils/include/mach.h b/utils/include/mach.h index f809aa2d..ea22b7e1 100644 --- a/utils/include/mach.h +++ b/utils/include/mach.h @@ -2,16 +2,21 @@ * Architecture-dependent application data */ #include "a.out.h" +#pragma src "/usr/inferno/utils/libmach" +#pragma lib "libmach.a" /* * Supported architectures: * mips, * 68020, * i386, + * amd64, * sparc, - * i960 (limited) - * 3210DSP (limited) + * sparc64, * mips2 (R4000) - * arm (limited) + * arm + * powerpc, + * powerpc64 + * alpha */ enum { @@ -19,14 +24,19 @@ enum MSPARC, M68020, MI386, - MI960, - M3210, + MI960, /* retired */ + M3210, /* retired */ MMIPS2, NMIPS2, - M29000, + M29000, /* retired */ MARM, MPOWER, - /* types of exectables */ + MALPHA, + NMIPS, + MSPARC64, + MAMD64, + MPOWER64, + /* types of executables */ FNONE = 0, /* unidentified */ FMIPS, /* v.out */ FMIPSB, /* mips bootable */ @@ -37,16 +47,24 @@ enum FNEXTB, /* Next bootable */ FI386, /* 8.out */ FI386B, /* I386 bootable */ - FI960, /* 6.out */ - FI960B, /* I960 bootable */ - F3210, /* x.out */ - FMIPS2BE, /* 4.out */ - F29000, /* 9.out */ + FI960, /* retired */ + FI960B, /* retired */ + F3210, /* retired */ + FMIPS2BE, /* 4.out */ + F29000, /* retired */ FARM, /* 5.out */ FARMB, /* ARM bootable */ FPOWER, /* q.out */ FPOWERB, /* power pc bootable */ - FMIPS2LE, /* 4k little endian */ + FMIPS2LE, /* 0.out */ + FALPHA, /* 7.out */ + FALPHAB, /* DEC Alpha bootable */ + FMIPSLE, /* 3k little endian */ + FSPARC64, /* u.out */ + FAMD64, /* 6.out */ + FAMD64B, /* 6.out bootable */ + FPOWER64, /* 9.out */ + FPOWER64B, /* 9.out bootable */ ANONE = 0, /* dissembler types */ AMIPS, @@ -56,22 +74,31 @@ enum A68020, AI386, AI8086, /* oh god */ - AI960, - A29000, + AI960, /* retired */ + A29000, /* retired */ AARM, APOWER, + AALPHA, + ASPARC64, + AAMD64, + APOWER64, /* object file types */ Obj68020 = 0, /* .2 */ ObjSparc, /* .k */ ObjMips, /* .v */ Obj386, /* .8 */ - Obj960, /* .6 */ - Obj3210, /* .x */ + Obj960, /* retired */ + Obj3210, /* retired */ ObjMips2, /* .4 */ - Obj29000, /* .9 */ + Obj29000, /* retired */ ObjArm, /* .5 */ ObjPower, /* .q */ ObjMips2le, /* .0 */ + ObjAlpha, /* .7 */ + ObjSparc64, /* .u */ + ObjAmd64, /* .6 */ + ObjSpim, /* .0 */ + ObjPower64, /* .9 */ Maxobjtype, CNONE = 0, /* symbol table classes */ @@ -80,7 +107,7 @@ enum CSTAB, CTEXT, CDATA, - CANY /* to look for any class */ + CANY, /* to look for any class */ }; typedef struct Map Map; @@ -88,6 +115,7 @@ typedef struct Symbol Symbol; typedef struct Reglist Reglist; typedef struct Mach Mach; typedef struct Machdata Machdata; + typedef struct segment segment; typedef int (*Rsegio)(segment*, ulong, long, char*, int); @@ -101,27 +129,27 @@ struct Map { char *name; /* the segment name */ int fd; /* file descriptor */ int inuse; /* in use - not in use */ - ulong b; /* base */ - ulong e; /* end */ - ulong f; /* offset within file */ - Rsegio mget; /* special get if not 0 */ - Rsegio mput; /* special put if not 0 */ + int cache; /* should cache reads? */ + uvlong b; /* base */ + uvlong e; /* end */ + vlong f; /* offset within file */ + Rsegio mget; /* special get if not nil */ + Rsegio mput; /* special put if not nil */ } seg[1]; /* actually n of these */ }; - - /* * Internal structure describing a symbol table entry */ struct Symbol { void *handle; /* used internally - owning func */ - /*struct {*/ + struct { char *name; - long value; /* address or stack offset */ + vlong value; /* address or stack offset */ char type; /* as in a.out.h */ char class; /* as above */ - /*};*/ + int index; /* in findlocal, globalsym, textsym */ + }; }; /* @@ -131,40 +159,40 @@ struct Reglist { char *rname; /* register name */ short roffs; /* offset in u-block */ char rflags; /* INTEGER/FLOAT, WRITABLE */ - char rformat; /* print format: 'x', 'X', 'f', '8' */ + char rformat; /* print format: 'x', 'X', 'f', '8', '3', 'Y', 'W' */ }; -enum { /* bits in rflags field */ +enum { /* bits in rflags field */ RINT = (0<<0), RFLT = (1<<0), RRDONLY = (1<<1) }; + /* * Machine-dependent data is stored in two structures: * Mach - miscellaneous general parameters * Machdata - jump vector of service functions used by debuggers * - * Mach is defined in 2.c, 4.c, v.c, k.c, 8.c, 6.c and set in executable.c + * Mach is defined in ?.c and set in executable.c * - * Machdata is defined in 2db.c, 4db.c, vdb.c, kdb.c, 8db.c, and 6db.c + * Machdata is defined in ?db.c * and set in the debugger startup. */ - - struct Mach{ char *name; int mtype; /* machine type code */ Reglist *reglist; /* register set */ - ulong regsize; /* sizeof registers in bytes*/ - ulong fpregsize; /* sizeof fp registers in bytes*/ + ulong regsize; /* sizeof registers in bytes */ + ulong fpregsize; /* sizeof fp registers in bytes */ char *pc; /* pc name */ char *sp; /* sp name */ char *link; /* link register name */ char *sbreg; /* static base register name */ - ulong sb; /* static base register value */ + uvlong sb; /* static base register value */ int pgsize; /* page size */ - ulong kbase; /* kernel base address */ - ulong ktmask; /* ktzero = kbase & ~ktmask */ + uvlong kbase; /* kernel base address */ + uvlong ktmask; /* ktzero = kbase & ~ktmask */ + uvlong utop; /* user stack top */ int pcquant; /* quantization of pc */ int szaddr; /* sizeof(void*) */ int szreg; /* sizeof(register) */ @@ -174,26 +202,26 @@ struct Mach{ extern Mach *mach; /* Current machine */ -typedef vlong (*Rgetter)(Map*, char*); -typedef void (*Tracer)(Map*, ulong, ulong, Symbol*); +typedef uvlong (*Rgetter)(Map*, char*); +typedef void (*Tracer)(Map*, uvlong, uvlong, Symbol*); struct Machdata { /* Machine-dependent debugger support */ uchar bpinst[4]; /* break point instr. */ short bpsize; /* size of break point instr. */ - ushort (*swab)(ushort); /* short to local byte order */ - long (*swal)(long); /* long to local byte order */ - vlong (*swav)(vlong); /* vlong to local byte order */ - int (*ctrace)(Map*, ulong, ulong, ulong, Tracer); /* C traceback */ - ulong (*findframe)(Map*, ulong, ulong, ulong, ulong);/* frame finder */ + ushort (*swab)(ushort); /* ushort to local byte order */ + ulong (*swal)(ulong); /* ulong to local byte order */ + uvlong (*swav)(uvlong); /* uvlong to local byte order */ + int (*ctrace)(Map*, uvlong, uvlong, uvlong, Tracer); /* C traceback */ + uvlong (*findframe)(Map*, uvlong, uvlong, uvlong, uvlong);/* frame finder */ char* (*excep)(Map*, Rgetter); /* last exception */ - ulong (*bpfix)(ulong); /* breakpoint fixup */ + ulong (*bpfix)(uvlong); /* breakpoint fixup */ int (*sftos)(char*, int, void*); /* single precision float */ int (*dftos)(char*, int, void*); /* double precision float */ - int (*foll)(Map*, ulong, Rgetter, ulong*); /* follow set */ - int (*das)(Map*, ulong, char, char*, int); /* symbolic disassembly */ - int (*hexinst)(Map*, ulong, char*, int); /* hex disassembly */ - int (*instsize)(Map*, ulong); /* instruction size */ + int (*foll)(Map*, uvlong, Rgetter, uvlong*);/* follow set */ + int (*das)(Map*, uvlong, char, char*, int); /* symbolic disassembly */ + int (*hexinst)(Map*, uvlong, char*, int); /* hex disassembly */ + int (*instsize)(Map*, uvlong); /* instruction size */ }; /* @@ -202,27 +230,29 @@ struct Machdata { /* Machine-dependent debugger support */ typedef struct Fhdr { char *name; /* identifier of executable */ - short type; /* file type - see codes above*/ - short hdrsz; /* size of this header */ + uchar type; /* file type - see codes above */ + uchar hdrsz; /* header size */ + uchar _magic; /* _MAGIC() magic */ + uchar spare; long magic; /* magic number */ - long txtaddr; /* text address */ - long entry; /* entry point */ + uvlong txtaddr; /* text address */ + vlong txtoff; /* start of text in file */ + uvlong dataddr; /* start of data segment */ + vlong datoff; /* offset to data seg in file */ + vlong symoff; /* offset of symbol table in file */ + uvlong entry; /* entry point */ + vlong sppcoff; /* offset of sp-pc table in file */ + vlong lnpcoff; /* offset of line number-pc table in file */ long txtsz; /* text size */ - long txtoff; /* start of text in file */ - long dataddr; /* start of data segment */ long datsz; /* size of data seg */ - long datoff; /* offset to data seg in file */ long bsssz; /* size of bss */ long symsz; /* size of symbol table */ - long symoff; /* offset of symbol table in file */ long sppcsz; /* size of sp-pc table */ - long sppcoff; /* offset of sp-pc table in file */ long lnpcsz; /* size of line number-pc table */ - long lnpcoff; /* size of line number-pc table */ } Fhdr; -extern int asstype; /* dissembler type - machdata.c */ -extern Machdata *machdata; /* jump vector - machdata.c */ +extern int asstype; /* dissembler type - machdata.c */ +extern Machdata *machdata; /* jump vector - machdata.c */ Map* attachproc(int, int, int, Fhdr*); Map* attachremt(int, Fhdr*); @@ -230,28 +260,28 @@ int beieee80ftos(char*, int, void*); int beieeesftos(char*, int, void*); int beieeedftos(char*, int, void*); ushort beswab(ushort); -long beswal(long); -vlong beswav(vlong); -int cisctrace(Map*, ulong, ulong, ulong, Tracer); -ulong ciscframe(Map*, ulong, ulong, ulong, ulong); +ulong beswal(ulong); +uvlong beswav(uvlong); +uvlong ciscframe(Map*, uvlong, uvlong, uvlong, uvlong); +int cisctrace(Map*, uvlong, uvlong, uvlong, Tracer); int crackhdr(int fd, Fhdr*); -long file2pc(char*, ulong); +uvlong file2pc(char*, long); int fileelem(Sym**, uchar *, char*, int); -int fileline(char*, int, ulong); +long fileline(char*, int, uvlong); int filesym(int, char*, int); int findlocal(Symbol*, char*, Symbol*); int findseg(Map*, char*); -int findsym(long, int, Symbol *); -int fnbound(long, ulong*); +int findsym(uvlong, int, Symbol *); +int fnbound(uvlong, uvlong*); int fpformat(Map*, Reglist*, char*, int, int); -int get1(Map*, ulong, uchar*, int); -int get2(Map*, ulong, ushort*); -int get4(Map*, ulong, long*); -int get8(Map*, ulong, vlong*); +int get1(Map*, uvlong, uchar*, int); +int get2(Map*, uvlong, ushort*); +int get4(Map*, uvlong, ulong*); +int get8(Map*, uvlong, uvlong*); +int geta(Map*, uvlong, uvlong*); int getauto(Symbol*, int, int, Symbol*); Sym* getsym(int); int globalsym(Symbol *, int); -int gsymoff(char*, int, long, int); char* _hexify(char*, ulong, int); int ieeesftos(char*, int, ulong); int ieeedftos(char*, int, ulong, ulong); @@ -260,11 +290,11 @@ int leieee80ftos(char*, int, void*); int leieeesftos(char*, int, void*); int leieeedftos(char*, int, void*); ushort leswab(ushort); -long leswal(long); -vlong leswav(vlong); -long line2addr(ulong, ulong, ulong); +ulong leswal(ulong); +uvlong leswav(uvlong); +uvlong line2addr(long, uvlong, uvlong); Map* loadmap(Map*, int, Fhdr*); -int localaddr(Map*, char*, char*, long*, Rgetter); +int localaddr(Map*, char*, char*, uvlong*, Rgetter); int localsym(Symbol*, int); int lookup(char*, char*, Symbol*); void machbytype(int); @@ -273,23 +303,24 @@ int nextar(Biobuf*, int, char*); Map* newmap(Map*, int); void objtraverse(void(*)(Sym*, void*), void*); int objtype(Biobuf*, char**); -long pc2sp(ulong); -long pc2line(ulong); -int put1(Map*, ulong, uchar*, int); -int put2(Map*, ulong, ushort); -int put4(Map*, ulong, long); -int put8(Map*, ulong, vlong); -int readar(Biobuf*, int, int, int); +uvlong pc2sp(uvlong); +long pc2line(uvlong); +int put1(Map*, uvlong, uchar*, int); +int put2(Map*, uvlong, ushort); +int put4(Map*, uvlong, ulong); +int put8(Map*, uvlong, uvlong); +int puta(Map*, uvlong, uvlong); +int readar(Biobuf*, int, vlong, int); int readobj(Biobuf*, int); -struct segment* reloc(Map*, ulong, long*); -ulong riscframe(Map*, ulong, ulong, ulong, ulong); -int risctrace(Map*, ulong, ulong, ulong, Tracer); -int setmap(Map*, int, ulong, ulong, ulong, char*); +uvlong riscframe(Map*, uvlong, uvlong, uvlong, uvlong); +int risctrace(Map*, uvlong, uvlong, uvlong, Tracer); +int setmap(Map*, int, uvlong, uvlong, vlong, char*); void setmapio(Map*, int, Rsegio, Rsegio); Sym* symbase(long*); int syminit(int, Fhdr*); -int symoff(char*, int, long, int); -void textseg(ulong, Fhdr*); +int symoff(char*, int, uvlong, int); +void textseg(uvlong, Fhdr*); int textsym(Symbol*, int); +void thumbpctab(Biobuf*, Fhdr*); +int thumbpclookup(uvlong); void unusemap(Map*, int); - diff --git a/utils/kc/gc.h b/utils/kc/gc.h index a081f4dd..577ba83d 100644 --- a/utils/kc/gc.h +++ b/utils/kc/gc.h @@ -256,7 +256,7 @@ void gpseudo(int, Sym*, Node*); int swcmp(const void*, const void*); void doswit(Node*); void swit1(C1*, int, long, Node*, Node*); -void cas(void); +void casf(void); void bitload(Node*, Node*, Node*, Node*, Node*); void bitstore(Node*, Node*, Node*, Node*, Node*); long outstring(char*, long); diff --git a/utils/kc/sgen.c b/utils/kc/sgen.c index 3836f2f3..105efcce 100644 --- a/utils/kc/sgen.c +++ b/utils/kc/sgen.c @@ -153,7 +153,7 @@ loop: if(cases == C) diag(n, "case/default outside a switch"); if(l == Z) { - cas(); + casf(); cases->val = 0; cases->def = 1; cases->label = pc; @@ -164,7 +164,7 @@ loop: goto rloop; if(l->op == OCONST) if(typechl[l->type->etype]) { - cas(); + casf(); cases->val = l->vconst; cases->def = 0; cases->label = pc; @@ -188,7 +188,7 @@ loop: cn = cases; cases = C; - cas(); + casf(); sbc = breakpc; breakpc = pc; diff --git a/utils/kc/swt.c b/utils/kc/swt.c index 6b812c2f..61633e91 100644 --- a/utils/kc/swt.c +++ b/utils/kc/swt.c @@ -94,7 +94,7 @@ swit1(C1 *q, int nc, long def, Node *n, Node *tn) } void -cas(void) +casf(void) { Case *c; diff --git a/utils/libmach/2.c b/utils/libmach/2.c index 2b1010f4..9d58b00b 100644 --- a/utils/libmach/2.c +++ b/utils/libmach/2.c @@ -75,8 +75,9 @@ Mach m68020 = "a6base", /* static base register name */ 0, /* value */ 0x2000, /* page size */ - 0x80000000, /* kernel base */ - 0, /* kernel text mask */ + 0x80000000U, /* kernel base */ + 0x80000000U, /* kernel text mask */ + 0x7FFFFFFFU, /* user stack top */ 2, /* quantization of pc */ 4, /* szaddr */ 4, /* szreg */ diff --git a/utils/libmach/2db.c b/utils/libmach/2db.c index 5aa61fd3..284df3c5 100644 --- a/utils/libmach/2db.c +++ b/utils/libmach/2db.c @@ -1,6 +1,6 @@ #include <lib9.h> #include <bio.h> -#include "mach.h" +#include <mach.h> /* * 68020-specific debugger interface @@ -8,10 +8,10 @@ static char *m68020excep(Map*, Rgetter); -static int m68020foll(Map*, ulong, Rgetter, ulong*); -static int m68020inst(Map*, ulong, char, char*, int); -static int m68020das(Map*, ulong, char*, int); -static int m68020instlen(Map*, ulong); +static int m68020foll(Map*, uvlong, Rgetter, uvlong*); +static int m68020inst(Map*, uvlong, char, char*, int); +static int m68020das(Map*, uvlong, char*, int); +static int m68020instlen(Map*, uvlong); Machdata m68020mach = { @@ -99,9 +99,10 @@ m68020ufix(Map *map) { struct ftype *ft; int i, size, vec; - ulong efl[2], stktop; + ulong efl[2]; uchar *ef=(uchar*)efl; - long l; + ulong l; + uvlong stktop; short fvo; /* The kernel proc pointer on a 68020 is always @@ -116,8 +117,8 @@ m68020ufix(Map *map) if ((l&0xfc000000) == 0x04000000) /* if NeXT */ size = 30*2; else - size = 46*2; /* 68020 */ - USED(size); /* kept because it might be re-used later */ + size = 46*2; /* 68020 */ + USED(size); stktop = mach->kbase+mach->pgsize; for(i=3; i<100; i++){ @@ -150,7 +151,7 @@ m68020ufix(Map *map) static char * m68020excep(Map *map, Rgetter rget) { - ulong pc; + uvlong pc; uchar buf[4]; if (m68020ufix(map) < 0) @@ -373,20 +374,20 @@ struct operand { int eatype; short ext; - union { + /*union {*/ long immediate; /* sign-extended integer byte/word/long */ - struct { /* index mode displacements */ + /*struct {*/ /* index mode displacements */ long disp; long outer; - } s0; + /*};*/ char floater[24]; /* floating point immediates */ - } u0; + /*};*/ }; struct inst { int n; /* # bytes in instruction */ - ulong addr; /* addr of start of instruction */ + uvlong addr; /* addr of start of instruction */ ushort raw[4+12]; /* longest instruction: 24 byte packed immediate */ Operand and[2]; char *end; /* end of print buffer */ @@ -911,7 +912,7 @@ dumpinst(Inst *ip, char *buf, int n) } static int -getword(Inst *ip, long offset) +getword(Inst *ip, uvlong offset) { if (ip->n < nelem(ip->raw)) { if (get2(mymap, offset, &ip->raw[ip->n++]) > 0) @@ -978,56 +979,55 @@ getimm(Inst *ip, Operand *ap, int mode) { case EAM_B: /* byte */ case EAALL_B: - return i8(ip, &ap->u0.immediate); + return i8(ip, &ap->immediate); case EADI_W: /* word */ case EAALL_W: - return i16(ip, &ap->u0.immediate); + return i16(ip, &ap->immediate); case EADI_L: /* long */ case EAALL_L: - return i32(ip, &ap->u0.immediate); + return i32(ip, &ap->immediate); case EAFLT: /* floating point - size in bits 10-12 or word 1 */ switch((ip->raw[1]>>10)&0x07) { case 0: /* long integer */ - return i32(ip, &ap->u0.immediate); + return i32(ip, &ap->immediate); case 1: /* single precision real */ ap->eatype = IREAL; - return getshorts(ip, ap->u0.floater, 2); + return getshorts(ip, ap->floater, 2); case 2: /* extended precision real - not supported */ ap->eatype = IEXT; - return getshorts(ip, ap->u0.floater, 6); + return getshorts(ip, ap->floater, 6); case 3: /* packed decimal real - not supported */ ap->eatype = IPACK; - return getshorts(ip, ap->u0.floater, 12); + return getshorts(ip, ap->floater, 12); case 4: /* integer word */ - return i16(ip, &ap->u0.immediate); + return i16(ip, &ap->immediate); case 5: /* double precision real */ ap->eatype = IDBL; - return getshorts(ip, ap->u0.floater, 4); + return getshorts(ip, ap->floater, 4); case 6: /* integer byte */ - return i8(ip, &ap->u0.immediate); + return i8(ip, &ap->immediate); default: ip->errmsg = "bad immediate float data"; return -1; } - break; + /* not reached */ case IV: /* size encoded in bits 6&7 of opcode word */ default: switch((ip->raw[0]>>6)&0x03) { case 0x00: /* integer byte */ - return i8(ip, &ap->u0.immediate); + return i8(ip, &ap->immediate); case 0x01: /* integer word */ - return i16(ip, &ap->u0.immediate); + return i16(ip, &ap->immediate); case 0x02: /* integer long */ - return i32(ip, &ap->u0.immediate); + return i32(ip, &ap->immediate); default: ip->errmsg = "bad immediate size"; return -1; } - break; + /* not reached */ } - return 1; } static int @@ -1040,9 +1040,9 @@ getdisp(Inst *ip, Operand *ap) ext = ip->raw[ip->n-1]; ap->ext = ext; if ((ext&0x100) == 0) { /* indexed with 7-bit displacement */ - ap->u0.s0.disp = ext&0x7f; - if (ap->u0.s0.disp&0x40) - ap->u0.s0.disp |= ~0x7f; + ap->disp = ext&0x7f; + if (ap->disp&0x40) + ap->disp |= ~0x7f; return 1; } switch(ext&0x30) /* first (inner) displacement */ @@ -1050,11 +1050,11 @@ getdisp(Inst *ip, Operand *ap) case 0x10: break; case 0x20: - if (i16(ip, &ap->u0.s0.disp) < 0) + if (i16(ip, &ap->disp) < 0) return -1; break; case 0x30: - if (i32(ip, &ap->u0.s0.disp) < 0) + if (i32(ip, &ap->disp) < 0) return -1; break; default: @@ -1064,9 +1064,9 @@ getdisp(Inst *ip, Operand *ap) switch (ext&0x03) /* outer displacement */ { case 0x02: /* 16 bit displacement */ - return i16(ip, &ap->u0.s0.outer); + return i16(ip, &ap->outer); case 0x03: /* 32 bit displacement */ - return i32(ip, &ap->u0.s0.outer); + return i32(ip, &ap->outer); default: break; } @@ -1105,7 +1105,7 @@ ea(Inst *ip, int ea, Operand *ap, int mode) case 0x05: ap->eatype = ADisp; type = Bdisp; - if (i16(ip, &ap->u0.s0.disp) < 0) + if (i16(ip, &ap->disp) < 0) return -1; break; case 0x06: @@ -1120,19 +1120,19 @@ ea(Inst *ip, int ea, Operand *ap, int mode) case 0x00: type = Abs; ap->eatype = ABS; - if (i16(ip, &ap->u0.immediate) < 0) + if (i16(ip, &ap->immediate) < 0) return -1; break; case 0x01: type = Abs; ap->eatype = ABS; - if (i32(ip, &ap->u0.immediate) < 0) + if (i32(ip, &ap->immediate) < 0) return -1; break; case 0x02: type = PCrel; ap->eatype = PDisp; - if (i16(ip, &ap->u0.s0.disp) < 0) + if (i16(ip, &ap->disp) < 0) return -1; break; case 0x03: @@ -1217,27 +1217,27 @@ decode(Inst *ip, Optable *op) break; case OP8: /* weird movq instruction */ ap->eatype = IMM; - ap->u0.immediate = opcode&0xff; + ap->immediate = opcode&0xff; if (opcode&0x80) - ap->u0.immediate |= ~0xff; + ap->immediate |= ~0xff; break; case I8: /* must be two-word opcode */ ap->eatype = IMM; - ap->u0.immediate = ip->raw[1]&0xff; - if (ap->u0.immediate&0x80) - ap->u0.immediate |= ~0xff; + ap->immediate = ip->raw[1]&0xff; + if (ap->immediate&0x80) + ap->immediate |= ~0xff; break; case I16: /* 16 bit immediate */ case BR16: ap->eatype = IMM; - if (i16(ip, &ap->u0.immediate) < 0) + if (i16(ip, &ap->immediate) < 0) return -1; break; case C16: /* CAS2 16 bit immediate */ ap->eatype = IMM; - if (i16(ip, &ap->u0.immediate) < 0) + if (i16(ip, &ap->immediate) < 0) return -1; - if (ap->u0.immediate & 0x0e38) { + if (ap->immediate & 0x0e38) { ip->errmsg = "bad CAS2W operand"; return 0; } @@ -1245,7 +1245,7 @@ decode(Inst *ip, Optable *op) case I32: /* 32 bit immediate */ case BR32: ap->eatype = IMM; - if (i32(ip, &ap->u0.immediate) < 0) + if (i32(ip, &ap->immediate) < 0) return -1; break; case IV: /* immediate data depends on size field */ @@ -1254,15 +1254,15 @@ decode(Inst *ip, Optable *op) break; case BR8: /* branch displacement format */ ap->eatype = IMM; - ap->u0.immediate = opcode&0xff; - if (ap->u0.immediate == 0) { - if (i16(ip, &ap->u0.immediate) < 0) + ap->immediate = opcode&0xff; + if (ap->immediate == 0) { + if (i16(ip, &ap->immediate) < 0) return -1; - } else if (ap->u0.immediate == 0xff) { - if (i32(ip, &ap->u0.immediate) < 0) + } else if (ap->immediate == 0xff) { + if (i32(ip, &ap->immediate) < 0) return -1; - } else if (ap->u0.immediate & 0x80) - ap->u0.immediate |= ~0xff; + } else if (ap->immediate & 0x80) + ap->immediate |= ~0xff; break; case STACK: /* Dummy operand type for Return instructions */ default: @@ -1299,6 +1299,8 @@ instruction(Inst *ip) return 0; } +#pragma varargck argpos bprint 2 + static void bprint(Inst *i, char *fmt, ...) { @@ -1318,11 +1320,12 @@ static char *regname[] = static void plocal(Inst *ip, Operand *ap) { - int ret, offset; - long moved; + int ret; + long offset; + uvlong moved; Symbol s; - offset = ap->u0.s0.disp; + offset = ap->disp; if (!findsym(ip->addr, CTEXT, &s)) goto none; @@ -1338,7 +1341,7 @@ plocal(Inst *ip, Operand *ap) if (ret) bprint(ip, "%s+%lux", s.name, offset); else -none: bprint(ip, "%lux", ap->u0.s0.disp); +none: bprint(ip, "%lux", ap->disp); } /* @@ -1401,7 +1404,7 @@ prindex(Inst *ip, int reg, Operand *ap) if (left <= 0) return; ext = ap->ext; - disp = ap->u0.s0.disp; + disp = ap->disp; /* look for static base register references */ if ((ext&0xa0) == 0x20 && reg == 14 && mach->sb && disp) { reg = 17; /* "A6" -> "SB" */ @@ -1429,7 +1432,7 @@ prindex(Inst *ip, int reg, Operand *ap) break; case 0x12: case 0x13: - ip->curr += symoff(ip->curr, left, ap->u0.s0.outer, CANY); + ip->curr += symoff(ip->curr, left, ap->outer, CANY); if (pidx(ip, ext, reg, "((%s)", "((%s)", 0)) bprint(ip, ")"); break; @@ -1439,7 +1442,7 @@ prindex(Inst *ip, int reg, Operand *ap) break; case 0x16: case 0x17: - ip->curr += symoff(ip->curr, left, ap->u0.s0.outer, CANY); + ip->curr += symoff(ip->curr, left, ap->outer, CANY); pidx(ip, ext, reg, "((%s))", "(%s)", 0); break; case 0x20: @@ -1464,7 +1467,7 @@ prindex(Inst *ip, int reg, Operand *ap) case 0x23: case 0x32: case 0x33: - ip->curr += symoff(ip->curr, left, ap->u0.s0.outer, CANY); + ip->curr += symoff(ip->curr, left, ap->outer, CANY); bprint(ip, "("); if (reg == 15) plocal(ip, ap); @@ -1487,7 +1490,7 @@ prindex(Inst *ip, int reg, Operand *ap) case 0x27: case 0x36: case 0x37: - ip->curr += symoff(ip->curr, left, ap->u0.s0.outer, CANY); + ip->curr += symoff(ip->curr, left, ap->outer, CANY); bprint(ip, "("); if (reg == 15) plocal(ip, ap); @@ -1528,53 +1531,53 @@ pea(int reg, Inst *ip, Operand *ap) bprint(ip, "-(A%d)", reg); break; case PDisp: - ip->curr += symoff(ip->curr, left, ip->addr+2+ap->u0.s0.disp, CANY); + ip->curr += symoff(ip->curr, left, ip->addr+2+ap->disp, CANY); break; case PXD: prindex(ip, 16, ap); break; case ADisp: /* references off the static base */ - if (reg == 6 && mach->sb && ap->u0.s0.disp) { - ip->curr += symoff(ip->curr, left, ap->u0.s0.disp+mach->sb, CANY); - bprint(ip, "(SB)", reg); + if (reg == 6 && mach->sb && ap->disp) { + ip->curr += symoff(ip->curr, left, ap->disp+mach->sb, CANY); + bprint(ip, "(SB)"); break; } /* reference autos and parameters off the stack */ if (reg == 7) plocal(ip, ap); else - ip->curr += symoff(ip->curr, left, ap->u0.s0.disp, CANY); + ip->curr += symoff(ip->curr, left, ap->disp, CANY); bprint(ip, "(A%d)", reg); break; case BXD: prindex(ip, reg+8, ap); break; case ABS: - ip->curr += symoff(ip->curr, left, ap->u0.immediate, CANY); + ip->curr += symoff(ip->curr, left, ap->immediate, CANY); bprint(ip, "($0)"); break; case IMM: *ip->curr++ = '$'; - ip->curr += symoff(ip->curr, left-1, ap->u0.immediate, CANY); + ip->curr += symoff(ip->curr, left-1, ap->immediate, CANY); break; case IREAL: *ip->curr++ = '$'; - ip->curr += beieeesftos(ip->curr, left-1, (void*) ap->u0.floater); + ip->curr += beieeesftos(ip->curr, left-1, (void*) ap->floater); break; case IDBL: *ip->curr++ = '$'; - ip->curr += beieeedftos(ip->curr, left-1, (void*) ap->u0.floater); + ip->curr += beieeedftos(ip->curr, left-1, (void*) ap->floater); break; case IPACK: bprint(ip, "$#"); for (i = 0; i < 24 && ip->curr < ip->end-1; i++) { - _hexify(ip->curr, ap->u0.floater[i], 1); + _hexify(ip->curr, ap->floater[i], 1); ip->curr += 2; } break; case IEXT: bprint(ip, "$#"); - ip->curr += beieee80ftos(ip->curr, left-2, (void*)ap->u0.floater); + ip->curr += beieee80ftos(ip->curr, left-2, (void*)ap->floater); break; default: bprint(ip, "??%x??", ap->eatype); @@ -1646,7 +1649,7 @@ formatins(char *fmt, Inst *ip) break; case 'i': /* immediate operand */ ip->curr += symoff(ip->curr, ip->end-ip->curr, - ip->and[currand++].u0.immediate, CANY); + ip->and[currand++].immediate, CANY); break; case 'j': /* data registers; word 1: [0-2] & [12-14] */ r1 = w1&0x07; @@ -1686,7 +1689,7 @@ formatins(char *fmt, Inst *ip) break; case 't': /* text offset */ ip->curr += symoff(ip->curr, ip->end-ip->curr, - ip->and[currand++].u0.immediate+ip->addr+2, CTEXT); + ip->and[currand++].immediate+ip->addr+2, CTEXT); break; case 'u': /* register number; word 1: [6-8] */ *ip->curr++ = ((w1>>6)&0x07)+'0'; @@ -1817,7 +1820,6 @@ immsize(Inst *ip, int mode) default: return isize[(ip->raw[0]>>6)&0x03]; } - return -1; } static int @@ -1902,7 +1904,7 @@ instrsize(Inst *ip, Optable *op) case BREAC: /* EAC JMP or CALL operand */ /* easy displacements for follow set */ if ((opcode&0x038) == 0x28 || (opcode&0x3f) == 0x3a) { - if (i16(ip, &ip->and[i].u0.immediate) < 0) + if (i16(ip, &ip->and[i].immediate) < 0) return -1; } else { t = easize(ip, opcode&0x3f, mode); @@ -1916,11 +1918,11 @@ instrsize(Inst *ip, Optable *op) ip->n++; break; case BR16: /* 16 bit branch displacement */ - if (i16(ip, &ip->and[i].u0.immediate) < 0) + if (i16(ip, &ip->and[i].immediate) < 0) return -1; break; case BR32: /* 32 bit branch displacement */ - if (i32(ip, &ip->and[i].u0.immediate) < 0) + if (i32(ip, &ip->and[i].immediate) < 0) return -1; break; case I32: /* 32 bit immediate */ @@ -1938,15 +1940,15 @@ instrsize(Inst *ip, Optable *op) case BR8: /* loony branch displacement format */ t = opcode&0xff; if (t == 0) { - if (i16(ip, &ip->and[i].u0.immediate) < 0) + if (i16(ip, &ip->and[i].immediate) < 0) return -1; } else if (t == 0xff) { - if (i32(ip, &ip->and[i].u0.immediate) < 0) + if (i32(ip, &ip->and[i].immediate) < 0) return -1; } else { - ip->and[i].u0.immediate = t; + ip->and[i].immediate = t; if (t & 0x80) - ip->and[i].u0.immediate |= ~0xff; + ip->and[i].immediate |= ~0xff; } break; case STACK: /* Dummy operand for Return instructions */ @@ -1972,19 +1974,19 @@ eaval(Inst *ip, Operand *ap, Rgetter rget) sprint(buf, "A%d", reg); return (*rget)(mymap, buf); case PDisp: - return ip->addr+2+ap->u0.s0.disp; + return ip->addr+2+ap->disp; case ADisp: sprint(buf, "A%d", reg); - return ap->u0.s0.disp+(*rget)(mymap, buf); + return ap->disp+(*rget)(mymap, buf); case ABS: - return ap->u0.immediate; + return ap->immediate; default: return 0; } } static int -m68020instlen(Map *map, ulong pc) +m68020instlen(Map *map, uvlong pc) { Inst i; Optable *op; @@ -1999,10 +2001,11 @@ m68020instlen(Map *map, ulong pc) } static int -m68020foll(Map *map, ulong pc, Rgetter rget, ulong *foll) +m68020foll(Map *map, uvlong pc, Rgetter rget, uvlong *foll) { int j; Inst i; + ulong l; Optable *op; mymap = map; @@ -2021,11 +2024,12 @@ m68020foll(Map *map, ulong pc, Rgetter rget, ulong *foll) case BR16: /* FBcc, FDBcc, DBcc */ case BR32: /* FBcc */ foll[0] = pc+i.n*2; - foll[1] = pc+2+i.and[j].u0.immediate; + foll[1] = pc+2+i.and[j].immediate; return 2; case STACK: /* RTR, RTS, RTD */ - if (get4(map, (*rget)(map, mach->sp), (long*) foll) < 0) + if (get4(map, (*rget)(map, mach->sp), &l) < 0) return -1; + *foll = l; return 1; default: break; @@ -2036,7 +2040,7 @@ m68020foll(Map *map, ulong pc, Rgetter rget, ulong *foll) } static int -m68020inst(Map *map, ulong pc, char modifier, char *buf, int n) +m68020inst(Map *map, uvlong pc, char modifier, char *buf, int n) { Inst i; Optable *op; @@ -2062,7 +2066,7 @@ m68020inst(Map *map, ulong pc, char modifier, char *buf, int n) } static int -m68020das(Map *map, ulong pc, char *buf, int n) +m68020das(Map *map, uvlong pc, char *buf, int n) { Inst i; Optable *op; diff --git a/utils/libmach/2obj.c b/utils/libmach/2obj.c index 368e1ec7..ad3540b7 100644 --- a/utils/libmach/2obj.c +++ b/utils/libmach/2obj.c @@ -3,6 +3,7 @@ */ #include <lib9.h> #include <bio.h> +#include <mach.h> #include "2c/2.out.h" #include "obj.h" @@ -42,9 +43,12 @@ _read2(Biobuf *bp, Prog *p) return 0; as |= ((c & 0xff) << 8); p->kind = aNone; + p->sig = 0; if(as == ANAME || as == ASIGNAME){ - if(as == ASIGNAME) - skip(bp, 4); /* signature */ + if(as == ASIGNAME){ + Bread(bp, &p->sig, 4); + p->sig = beswal(p->sig); + } p->kind = aName; p->type = type2char(Bgetc(bp)); /* type */ p->sym = Bgetc(bp); /* sym */ diff --git a/utils/libmach/5db.c b/utils/libmach/5db.c index 8312487c..535739e8 100644 --- a/utils/libmach/5db.c +++ b/utils/libmach/5db.c @@ -17,7 +17,7 @@ struct Instr { Map *map; ulong w; - ulong addr; + uvlong addr; uchar op; /* super opcode */ uchar cond; /* bits 28-31 */ @@ -38,7 +38,7 @@ struct Opcode { char* o; void (*fmt)(Opcode*, Instr*); - ulong (*foll)(Map*, Rgetter, Instr*, ulong); + uvlong (*foll)(Map*, Rgetter, Instr*, uvlong); char* a; }; @@ -49,11 +49,11 @@ static char FRAMENAME[] = ".frame"; * Arm-specific debugger interface */ -extern char *armexcep(Map*, Rgetter); -static int armfoll(Map*, ulong, Rgetter, ulong*); -static int arminst(Map*, ulong, char, char*, int); -static int armdas(Map*, ulong, char*, int); -static int arminstlen(Map*, ulong); +static char *armexcep(Map*, Rgetter); +static int armfoll(Map*, uvlong, Rgetter, uvlong*); +static int arminst(Map*, uvlong, char, char*, int); +static int armdas(Map*, uvlong, char*, int); +static int arminstlen(Map*, uvlong); /* * Debugger interface @@ -78,13 +78,13 @@ Machdata armmach = arminstlen, /* instruction size */ }; -char* +static char* armexcep(Map *map, Rgetter rget) { - long c; + uvlong c; c = (*rget)(map, "TYPE"); - switch (c&0x1f) { + switch ((int)c&0x1f) { case 0x11: return "Fiq interrupt"; case 0x12: @@ -148,11 +148,16 @@ armclass(long w) op++; /* swap */ break; } + if(w & (1<<23)) { /* mullu */ + op = (48+24+4+4+2+2+4); + if(w & (1<<22)) /* mull */ + op += 2; + } if(w & (1<<21)) op++; /* mla */ break; } - if ((op & 0x9) == 0x9) /* ld/st byte/half s/u */ + if((op & 0x9) == 0x9) /* ld/st byte/half s/u */ { op = (48+16+4) + ((w >> 22) & 0x1) + ((w >> 19) & 0x2); break; @@ -161,7 +166,7 @@ armclass(long w) if(w & (1<<4)) op += 32; else - if(w & (31<<7)) + if((w & (31<<7)) || (w & (1<<5))) op += 16; break; case 1: /* data processing i,r,r */ @@ -183,16 +188,16 @@ armclass(long w) op = (48+24+4+4+2+2) + ((w >> 3) & 0x2) + ((w >> 20) & 0x1); break; default: - op = (48+24+4+4+2+2+4); + op = (48+24+4+4+2+2+4+4); break; } return op; } static int -decode(Map *map, ulong pc, Instr *i) +decode(Map *map, uvlong pc, Instr *i) { - long w; + ulong w; if(get4(map, pc, &w) < 0) { werrstr("can't read instruction: %r"); @@ -206,6 +211,8 @@ decode(Map *map, ulong pc, Instr *i) return 1; } +#pragma varargck argpos bprint 2 + static void bprint(Instr *i, char *fmt, ...) { @@ -226,7 +233,7 @@ plocal(Instr *i) int offset; if(!findsym(i->addr, CTEXT, &s)) { - if(debug)fprint(2,"fn not found @%lux: %r\n", i->addr); + if(debug)fprint(2,"fn not found @%llux: %r\n", i->addr); return 0; } fn = s.name; @@ -248,14 +255,14 @@ plocal(Instr *i) class == CAUTO ? " auto" : "param", offset); return 0; } - bprint(i, "%s%c%d%s", s.name, class == CPARAM ? '+' : '-', s.value, reg); + bprint(i, "%s%c%lld%s", s.name, class == CPARAM ? '+' : '-', s.value, reg); return 1; } /* * Print value v as name[+offset] */ -int +static int gsymoff(char *buf, int n, long v, int space) { Symbol s; @@ -277,7 +284,7 @@ gsymoff(char *buf, int n, long v, int space) if (!delta) return snprint(buf, n, "%s", s.name); if (s.type != 't' && s.type != 'T') - return snprint(buf, n, "%s+%lux", s.name, v-s.value); + return snprint(buf, n, "%s+%llux", s.name, v-s.value); else return snprint(buf, n, "#%lux", v); } @@ -454,7 +461,7 @@ armco(Opcode *o, Instr *i) /* coprocessor instructions */ static int armcondpass(Map *map, Rgetter rget, uchar cond) { - ulong psr; + uvlong psr; uchar n; uchar z; uchar c; @@ -467,24 +474,24 @@ armcondpass(Map *map, Rgetter rget, uchar cond) v = (psr >> 28) & 1; switch(cond) { - case 0: return z; - case 1: return !z; - case 2: return c; - case 3: return !c; - case 4: return n; - case 5: return !n; - case 6: return v; - case 7: return !v; - case 8: return c && !z; - case 9: return !c || z; - case 10: return n == v; - case 11: return n != v; - case 12: return !z && (n == v); - case 13: return z && (n != v); - case 14: return 1; - case 15: return 0; + default: + case 0: return z; + case 1: return !z; + case 2: return c; + case 3: return !c; + case 4: return n; + case 5: return !n; + case 6: return v; + case 7: return !v; + case 8: return c && !z; + case 9: return !c || z; + case 10: return n == v; + case 11: return n != v; + case 12: return !z && (n == v); + case 13: return z && (n != v); + case 14: return 1; + case 15: return 0; } - return 0; } static ulong @@ -503,6 +510,7 @@ armshiftval(Map *map, Rgetter rget, Instr *i) v = rget(map, buf); switch((i->w & BITS(4, 6)) >> 4) { + default: case 0: /* LSLIMM */ return v << s; case 1: /* LSLREG */ @@ -548,7 +556,6 @@ armshiftval(Map *map, Rgetter rget, Instr *i) return ROR(v, s & 0xF); } } - return 0; } static int @@ -580,15 +587,15 @@ armmaddr(Map *map, Rgetter rget, Instr *i) nb = nbits(i->w & ((1 << 15) - 1)); switch((i->w >> 23) & 3) { - case 0: return (v - (nb*4)) + 4; - case 1: return v; - case 2: return v - (nb*4); - case 3: return v + 4; + default: + case 0: return (v - (nb*4)) + 4; + case 1: return v; + case 2: return v - (nb*4); + case 3: return v + 4; } - return 0; } -static ulong +static uvlong armaddr(Map *map, Rgetter rget, Instr *i) { char buf[8]; @@ -634,8 +641,8 @@ armaddr(Map *map, Rgetter rget, Instr *i) } } -static ulong -armfadd(Map *map, Rgetter rget, Instr *i, ulong pc) +static uvlong +armfadd(Map *map, Rgetter rget, Instr *i, uvlong pc) { char buf[8]; int r; @@ -650,8 +657,8 @@ armfadd(Map *map, Rgetter rget, Instr *i, ulong pc) return rget(map, buf) + armshiftval(map, rget, i); } -static ulong -armfmovm(Map *map, Rgetter rget, Instr *i, ulong pc) +static uvlong +armfmovm(Map *map, Rgetter rget, Instr *i, uvlong pc) { ulong v; ulong addr; @@ -661,15 +668,15 @@ armfmovm(Map *map, Rgetter rget, Instr *i, ulong pc) return pc+4; addr = armmaddr(map, rget, i) + nbits(i->w & BITS(0,15)); - if(get4(map, addr, (long*)&v) < 0) { + if(get4(map, addr, &v) < 0) { werrstr("can't read addr: %r"); return -1; } return v; } -static ulong -armfbranch(Map *map, Rgetter rget, Instr *i, ulong pc) +static uvlong +armfbranch(Map *map, Rgetter rget, Instr *i, uvlong pc) { if(!armcondpass(map, rget, (i->w >> 28) & 0xf)) return pc+4; @@ -677,11 +684,10 @@ armfbranch(Map *map, Rgetter rget, Instr *i, ulong pc) return pc + (((signed long)i->w << 8) >> 6) + 8; } -static ulong -armfmov(Map *map, Rgetter rget, Instr *i, ulong pc) +static uvlong +armfmov(Map *map, Rgetter rget, Instr *i, uvlong pc) { - ulong rd; - ulong v; + ulong rd, v; rd = (i->w >> 12) & 0xf; if(rd != 15 || !armcondpass(map, rget, (i->w>>28)&0xf)) @@ -690,7 +696,7 @@ armfmov(Map *map, Rgetter rget, Instr *i, ulong pc) /* LDR */ /* BUG: Needs LDH/B, too */ if(((i->w>>26)&0x3) == 1) { - if(get4(map, armaddr(map, rget, i), (long*)&v) < 0) { + if(get4(map, armaddr(map, rget, i), &v) < 0) { werrstr("can't read instruction: %r"); return pc+4; } @@ -698,7 +704,9 @@ armfmov(Map *map, Rgetter rget, Instr *i, ulong pc) } /* MOV */ - return armshiftval(map, rget, i); + v = armshiftval(map, rget, i); + + return v; } static Opcode opcodes[] = @@ -775,8 +783,8 @@ static Opcode opcodes[] = "MVN%C%S", armdpi, 0, "$#%i,R%d", /* 48+16 */ - "MUL%C%S", armdpi, 0, "R%s,R%M,R%n", - "MULA%C%S", armdpi, 0, "R%s,R%M,R%n,R%d", + "MUL%C%S", armdpi, 0, "R%M,R%s,R%n", + "MULA%C%S", armdpi, 0, "R%M,R%s,R%n,R%d", "SWPW", armdpi, 0, "R%s,(R%n),R%d", "SWPB", armdpi, 0, "R%s,(R%n),R%d", @@ -808,6 +816,13 @@ static Opcode opcodes[] = "MCR%C", armco, 0, "", "MRC%C", armco, 0, "", +/* 48+24+4+4+2+2+4 */ + "MULLU%C%S", armdpi, 0, "R%M,R%s,(R%n,R%d)", + "MULALU%C%S", armdpi, 0, "R%M,R%s,(R%n,R%d)", + "MULL%C%S", armdpi, 0, "R%M,R%s,(R%n,R%d)", + "MULAL%C%S", armdpi, 0, "R%M,R%s,(R%n,R%d)", + +/* 48+24+4+4+2+2+4+4 */ "UNK", armunk, 0, "", }; @@ -874,11 +889,11 @@ format(char *mnemonic, Instr *i, char *f) break; case 'M': - bprint(i, "%d", (i->w>>8) & 0xf); + bprint(i, "%lud", (i->w>>8) & 0xf); break; case 'm': - bprint(i, "%d", (i->w>>7) & 0x1f); + bprint(i, "%lud", (i->w>>7) & 0x1f); break; case 'h': @@ -898,7 +913,7 @@ format(char *mnemonic, Instr *i, char *f) fmt = "#%lx(R%d)"; if (i->rn == 15) { /* convert load of offset(PC) to a load immediate */ - if (get4(i->map, i->addr+i->imm+8, &i->imm) > 0) + if (get4(i->map, i->addr+i->imm+8, (ulong*)&i->imm) > 0) { g = 1; fmt = ""; @@ -909,7 +924,7 @@ format(char *mnemonic, Instr *i, char *f) if (i->rd == 11) { ulong nxti; - if (get4(i->map, i->addr+4, (long*)&nxti) > 0) { + if (get4(i->map, i->addr+4, &nxti) > 0) { if ((nxti & 0x0e0f0fff) == 0x060c000b) { i->imm += mach->sb; g = 1; @@ -995,7 +1010,7 @@ format(char *mnemonic, Instr *i, char *f) } static int -printins(Map *map, ulong pc, char *buf, int n) +printins(Map *map, uvlong pc, char *buf, int n) { Instr i; @@ -1009,14 +1024,14 @@ printins(Map *map, ulong pc, char *buf, int n) } static int -arminst(Map *map, ulong pc, char modifier, char *buf, int n) +arminst(Map *map, uvlong pc, char modifier, char *buf, int n) { USED(modifier); return printins(map, pc, buf, n); } static int -armdas(Map *map, ulong pc, char *buf, int n) +armdas(Map *map, uvlong pc, char *buf, int n) { Instr i; @@ -1031,7 +1046,7 @@ armdas(Map *map, ulong pc, char *buf, int n) } static int -arminstlen(Map *map, ulong pc) +arminstlen(Map *map, uvlong pc) { Instr i; @@ -1041,9 +1056,9 @@ arminstlen(Map *map, ulong pc) } static int -armfoll(Map *map, ulong pc, Rgetter rget, ulong *foll) +armfoll(Map *map, uvlong pc, Rgetter rget, uvlong *foll) { - ulong d; + uvlong d; Instr i; if(decode(map, pc, &i) < 0) diff --git a/utils/libmach/6.c b/utils/libmach/6.c index 28c74a43..459d1191 100644 --- a/utils/libmach/6.c +++ b/utils/libmach/6.c @@ -1,16 +1,12 @@ /* - * x86-amd64 definition + * amd64 definition */ #include <lib9.h> #include <bio.h> #include "ureg6.h" #include "mach.h" -#define REGOFF(x) (uvlong)(&((struct Ureg *) 0)->x) - -#define PC REGOFF(pc) -#define SP REGOFF(sp) -#define AX REGOFF(ax) +#define REGOFF(x) offsetof(struct Ureg, x) #define REGSIZE sizeof(struct Ureg) #define FP_CTLS(x) (REGSIZE+2*(x)) @@ -21,41 +17,43 @@ #define FPREGSIZE 512 /* TO DO? currently only 0x1A0 used */ Reglist amd64reglist[] = { - {"R15", REGOFF(r15), RINT, 'Y'}, - {"R14", REGOFF(r14), RINT, 'Y'}, - {"R13", REGOFF(r13), RINT, 'Y'}, - {"R12", REGOFF(r12), RINT, 'Y'}, - {"R11", REGOFF(r11), RINT, 'Y'}, - {"R10", REGOFF(r10), RINT, 'Y'}, - {"R9", REGOFF(r9), RINT, 'Y'}, - {"R8", REGOFF(r8), RINT, 'Y'}, - {"DI", REGOFF(di), RINT, 'X'}, - {"SI", REGOFF(si), RINT, 'Y'}, - {"BP", REGOFF(bp), RINT, 'Y'}, + {"AX", REGOFF(ax), RINT, 'Y'}, {"BX", REGOFF(bx), RINT, 'Y'}, - {"DX", REGOFF(dx), RINT, 'Y'}, {"CX", REGOFF(cx), RINT, 'Y'}, - {"AX", REGOFF(ax), RINT, 'Y'}, - {"GS", REGOFF(gs), RINT, 'Y'}, - {"FS", REGOFF(fs), RINT, 'Y'}, - {"ES", REGOFF(es), RINT, 'Y'}, - {"DS", REGOFF(ds), RINT, 'Y'}, - {"TRAP", REGOFF(trap), RINT, 'Y'}, - {"ECODE", REGOFF(ecode), RINT, 'Y'}, - {"PC", PC, RINT, 'Y'}, + {"DX", REGOFF(dx), RINT, 'Y'}, + {"SI", REGOFF(si), RINT, 'Y'}, + {"DI", REGOFF(di), RINT, 'Y'}, + {"BP", REGOFF(bp), RINT, 'Y'}, + {"R8", REGOFF(r8), RINT, 'Y'}, + {"R9", REGOFF(r9), RINT, 'Y'}, + {"R10", REGOFF(r10), RINT, 'Y'}, + {"R11", REGOFF(r11), RINT, 'Y'}, + {"R12", REGOFF(r12), RINT, 'Y'}, + {"R13", REGOFF(r13), RINT, 'Y'}, + {"R14", REGOFF(r14), RINT, 'Y'}, + {"R15", REGOFF(r15), RINT, 'Y'}, + {"DS", REGOFF(ds), RINT, 'x'}, + {"ES", REGOFF(es), RINT, 'x'}, + {"FS", REGOFF(fs), RINT, 'x'}, + {"GS", REGOFF(gs), RINT, 'x'}, + {"TYPE", REGOFF(type), RINT, 'Y'}, + {"TRAP", REGOFF(type), RINT, 'Y'}, /* alias for acid */ + {"ERROR", REGOFF(error), RINT, 'Y'}, + {"IP", REGOFF(ip), RINT, 'Y'}, + {"PC", REGOFF(ip), RINT, 'Y'}, /* alias for acid */ {"CS", REGOFF(cs), RINT, 'Y'}, - {"EFLAGS", REGOFF(flags), RINT, 'Y'}, - {"SP", SP, RINT, 'Y'}, + {"FLAGS", REGOFF(flags), RINT, 'Y'}, + {"SP", REGOFF(sp), RINT, 'Y'}, {"SS", REGOFF(ss), RINT, 'Y'}, {"FCW", FP_CTLS(0), RFLT, 'x'}, {"FSW", FP_CTLS(1), RFLT, 'x'}, - {"FTW", FP_CTLS(2), RFLT, 'x'}, + {"FTW", FP_CTLS(2), RFLT, 'b'}, {"FOP", FP_CTLS(3), RFLT, 'x'}, - {"FPC", FP_CTL(2), RFLT, 'Y'}, + {"RIP", FP_CTL(2), RFLT, 'Y'}, {"RDP", FP_CTL(4), RFLT, 'Y'}, - {"MXCSR", FP_CTL(6), RFLT, 'X'}, - {"MXCSRMSK", FP_CTL(7), RFLT, 'X'}, + {"MXCSR", FP_CTL(6), RFLT, 'X'}, + {"MXCSRMASK", FP_CTL(7), RFLT, 'X'}, {"M0", FP_REG(0), RFLT, 'F'}, /* assumes double */ {"M1", FP_REG(1), RFLT, 'F'}, {"M2", FP_REG(2), RFLT, 'F'}, @@ -97,21 +95,22 @@ Reglist amd64reglist[] = { Mach mamd64= { "amd64", - MI386, /* machine type */ /* TO DO */ - amd64reglist, /* register list */ - REGSIZE, /* size of registers in bytes */ - FPREGSIZE, /* size of fp registers in bytes */ - "PC", /* name of PC */ - "SP", /* name of SP */ - 0, /* link register */ - "setSB", /* static base register name (bogus anyways) */ - 0, /* static base register value */ - 0x1000, /* page size */ - 0x80100000, /* kernel base */ /* TO DO: uvlong or vlong */ - 0, /* kernel text mask */ - 1, /* quantization of pc */ - 8, /* szaddr */ - 4, /* szreg */ - 4, /* szfloat */ - 8, /* szdouble */ + MAMD64, /* machine type */ + amd64reglist, /* register list */ + REGSIZE, /* size of registers in bytes */ + FPREGSIZE, /* size of fp registers in bytes */ + "PC", /* name of PC */ + "SP", /* name of SP */ + 0, /* link register */ + "setSB", /* static base register name (bogus anyways) */ + 0, /* static base register value */ + 0x1000, /* page size */ + 0xFFFFFFFF80110000ULL, /* kernel base */ + 0xFFFF800000000000ULL, /* kernel text mask */ + 0x00007FFFFFFFF000ULL, /* user stack top */ + 1, /* quantization of pc */ + 8, /* szaddr */ + 4, /* szreg */ + 4, /* szfloat */ + 8, /* szdouble */ }; diff --git a/utils/libmach/6obj.c b/utils/libmach/6obj.c index 7fb95115..d4c72af6 100644 --- a/utils/libmach/6obj.c +++ b/utils/libmach/6obj.c @@ -3,6 +3,7 @@ */ #include <lib9.h> #include <bio.h> +#include <mach.h> #include "6c/6.out.h" #include "obj.h" @@ -42,9 +43,12 @@ _read6(Biobuf *bp, Prog* p) return 0; as |= ((c & 0xff) << 8); p->kind = aNone; + p->sig = 0; if(as == ANAME || as == ASIGNAME){ - if(as == ASIGNAME) - skip(bp, 4); /* signature */ + if(as == ASIGNAME){ + Bread(bp, &p->sig, 4); + p->sig = leswal(p->sig); + } p->kind = aName; p->type = type2char(Bgetc(bp)); /* type */ p->sym = Bgetc(bp); /* sym */ diff --git a/utils/libmach/8db.c b/utils/libmach/8db.c index 86b6e1f2..7177c815 100644 --- a/utils/libmach/8db.c +++ b/utils/libmach/8db.c @@ -4,53 +4,49 @@ /* * i386-specific debugger interface + * also amd64 extensions */ static char *i386excep(Map*, Rgetter); -static int i386trace(Map*, ulong, ulong, ulong, Tracer); -static ulong i386frame(Map*, ulong, ulong, ulong, ulong); -static int i386foll(Map*, ulong, Rgetter, ulong*); -static int i386inst(Map*, ulong, char, char*, int); -static int i386das(Map*, ulong, char*, int); -static int i386instlen(Map*, ulong); +static int i386trace(Map*, uvlong, uvlong, uvlong, Tracer); +static uvlong i386frame(Map*, uvlong, uvlong, uvlong, uvlong); +static int i386foll(Map*, uvlong, Rgetter, uvlong*); +static int i386inst(Map*, uvlong, char, char*, int); +static int i386das(Map*, uvlong, char*, int); +static int i386instlen(Map*, uvlong); static char STARTSYM[] = "_main"; static char PROFSYM[] = "_mainp"; static char FRAMENAME[] = ".frame"; static char *excname[] = { - "divide error", /* 0 */ - "debug exception", /* 1 */ - 0,0, /* 2, 3 */ - "overflow", /* 4 */ - "bounds check", /* 5 */ - "invalid opcode", /* 6 */ - "math coprocessor emulation", /* 7 */ - "double fault", /* 8 */ - "math coprocessor overrun", /* 9 */ - "invalid TSS", /* 10 */ - "segment not present", /* 11 */ - "stack exception", /* 12 */ - "general protection violation", /* 13 */ - "page fault", /* 14 */ - 0, /* 15 */ - "math coprocessor error", /* 16 */ - 0,0,0,0,0,0,0, /* 17-23 */ - "clock", /* 24 */ - "keyboard", /* 25 */ - 0, /* 26 */ - "modem status", /* 27 */ - "serial line status", /* 28 */ - 0, /* 29 */ - "floppy disk", /* 30 */ - 0,0,0,0,0, /* 31-35 */ - "mouse", /* 36 */ - "math coprocessor", /* 37 */ - "hard disk", /* 38 */ - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,/* 39-54 */ - 0,0,0,0,0,0,0,0,0, /* 55-63 */ - "system call", /* 64 */ +[0] "divide error", +[1] "debug exception", +[4] "overflow", +[5] "bounds check", +[6] "invalid opcode", +[7] "math coprocessor emulation", +[8] "double fault", +[9] "math coprocessor overrun", +[10] "invalid TSS", +[11] "segment not present", +[12] "stack exception", +[13] "general protection violation", +[14] "page fault", +[16] "math coprocessor error", +[17] "alignment check", +[18] "machine check", +[19] "floating-point exception", +[24] "clock", +[25] "keyboard", +[27] "modem status", +[28] "serial line status", +[30] "floppy disk", +[36] "mouse", +[37] "math coprocessor", +[38] "hard disk", +[64] "system call", }; Machdata i386mach = @@ -77,7 +73,7 @@ static char* i386excep(Map *map, Rgetter rget) { ulong c; - ulong pc; + uvlong pc; static char buf[16]; c = (*rget)(map, "TRAP"); @@ -88,17 +84,17 @@ i386excep(Map *map, Rgetter rget) if (memcmp(buf, machdata->bpinst, machdata->bpsize) == 0) return "breakpoint"; } - sprint(buf, "exception %ld", c); + snprint(buf, sizeof(buf), "exception %ld", c); return buf; } else return excname[c]; } static int -i386trace(Map *map, ulong pc, ulong sp, ulong link, Tracer trace) +i386trace(Map *map, uvlong pc, uvlong sp, uvlong link, Tracer trace) { int i; - ulong osp; + uvlong osp; Symbol s, f; USED(link); @@ -118,7 +114,7 @@ i386trace(Map *map, ulong pc, ulong sp, ulong link, Tracer trace) sp += f.value-mach->szaddr; } - if (get4(map, sp, (long *) &pc) < 0) + if (geta(map, sp, &pc) < 0) break; if(pc == 0) @@ -127,14 +123,14 @@ i386trace(Map *map, ulong pc, ulong sp, ulong link, Tracer trace) (*trace)(map, pc, sp, &s); sp += mach->szaddr; - if(++i > 40) + if(++i > 1000) break; } return i; } -static ulong -i386frame(Map *map, ulong addr, ulong pc, ulong sp, ulong link) +static uvlong +i386frame(Map *map, uvlong addr, uvlong pc, uvlong sp, uvlong link) { Symbol s, f; @@ -152,7 +148,7 @@ i386frame(Map *map, ulong addr, ulong pc, ulong sp, ulong link) if (s.value == addr) return sp; - if (get4(map, sp, (long *)&pc) < 0) + if (geta(map, sp, &pc) < 0) break; sp += mach->szaddr; } @@ -168,22 +164,27 @@ typedef struct Instr Instr; struct Instr { uchar mem[1+1+1+1+2+1+1+4+4]; /* raw instruction */ - ulong addr; /* address of start of instruction */ + uvlong addr; /* address of start of instruction */ int n; /* number of bytes in instruction */ char *prefix; /* instr prefix */ char *segment; /* segment override */ uchar jumptype; /* set to the operand type for jump/ret/call */ - char osize; /* 'W' or 'L' */ - char asize; /* address size 'W' or 'L' */ + uchar amd64; + uchar rex; /* REX prefix (or zero) */ + char osize; /* 'W' or 'L' (or 'Q' on amd64) */ + char asize; /* address size 'W' or 'L' (or 'Q' or amd64) */ uchar mod; /* bits 6-7 of mod r/m field */ uchar reg; /* bits 3-5 of mod r/m field */ char ss; /* bits 6-7 of SIB */ char index; /* bits 3-5 of SIB */ char base; /* bits 0-2 of SIB */ + char rip; /* RIP-relative in amd64 mode */ + uchar opre; /* f2/f3 could introduce media */ short seg; /* segment of far address */ ulong disp; /* displacement */ ulong imm; /* immediate */ ulong imm2; /* second immediate operand */ + uvlong imm64; /* big immediate */ char *curr; /* fill level in output buffer */ char *end; /* end of output buffer */ char *err; /* error message */ @@ -199,7 +200,26 @@ enum{ BP, SI, DI, + + /* amd64 */ + R8, + R9, + R10, + R11, + R12, + R13, + R14, + R15 }; + + /* amd64 rex extension byte */ +enum{ + REXW = 1<<3, /* =1, 64-bit operand size */ + REXR = 1<<2, /* extend modrm reg */ + REXX = 1<<1, /* extend sib index */ + REXB = 1<<0 /* extend modrm r/m, sib base, or opcode reg */ +}; + /* Operand Format codes */ /* %A - address size register modifier (!asize -> 'E') @@ -209,7 +229,7 @@ enum{ %O - Operand size register modifier (!osize -> 'E') %T - Test register TR6/TR7 %S - size code ('W' or 'L') -%X - Weird opcode: OSIZE == 'W' => "CBW"; else => "CWDE" +%W - Weird opcode: OSIZE == 'W' => "CBW"; else => "CWDE" %d - displacement 16-32 bits %e - effective address - Mod R/M value %f - floating point register F0-F7 - from Mod R/M register @@ -217,7 +237,7 @@ enum{ %i - immediate operand 8-32 bits %p - PC-relative - signed displacement in immediate field %r - Reg from Mod R/M -%x - Weird opcode: OSIZE == 'W' => "CWD"; else => "CDQ" +%w - Weird opcode: OSIZE == 'W' => "CWD"; else => "CDQ" */ typedef struct Optable Optable; @@ -234,6 +254,7 @@ enum { Iw, /* 16-bit immediate -> imm */ Iw2, /* 16-bit immediate -> imm2 */ Iwd, /* Operand-sized immediate (no sign extension)*/ + Iwdq, /* Operand-sized immediate, possibly 64 bits */ Awd, /* Address offset */ Iwds, /* Operand-sized immediate (sign extended) */ RM, /* Word or long R/M field with register (/r) */ @@ -251,7 +272,9 @@ enum { OA, /* literal 0x0a byte */ PTR, /* Seg:Displacement addr (ptr16:16 or ptr16:32) */ AUX, /* Multi-byte op code - Auxiliary table */ + AUXMM, /* multi-byte op code - auxiliary table chosen by prefix */ PRE, /* Instr Prefix */ + OPRE, /* Instr Prefix or media op extension */ SEG, /* Segment Prefix */ OPOVER, /* Operand size override */ ADDOVER, /* Address size override */ @@ -259,359 +282,499 @@ enum { static Optable optab0F00[8]= { - 0,0, "MOVW LDT,%e", /* 0x00 */ - 0,0, "MOVW TR,%e", /* 0x01 */ - 0,0, "MOVW %e,LDT", /* 0x02 */ - 0,0, "MOVW %e,TR", /* 0x03 */ - 0,0, "VERR %e", /* 0x04 */ - 0,0, "VERW %e", /* 0x05 */ +[0x00] 0,0, "MOVW LDT,%e", +[0x01] 0,0, "MOVW TR,%e", +[0x02] 0,0, "MOVW %e,LDT", +[0x03] 0,0, "MOVW %e,TR", +[0x04] 0,0, "VERR %e", +[0x05] 0,0, "VERW %e", }; static Optable optab0F01[8]= { - 0,0, "MOVL GDTR,%e", /* 0x00 */ - 0,0, "MOVL IDTR,%e", /* 0x01 */ - 0,0, "MOVL %e,GDTR", /* 0x02 */ - 0,0, "MOVL %e,IDTR", /* 0x03 */ - 0,0, "MOVW MSW,%e", /* 0x04 */ /* word */ - 0,0, "", /* 0x05 */ - 0,0, "MOVW %e,MSW", /* 0x06 */ /* word */ +[0x00] 0,0, "MOVL GDTR,%e", +[0x01] 0,0, "MOVL IDTR,%e", +[0x02] 0,0, "MOVL %e,GDTR", +[0x03] 0,0, "MOVL %e,IDTR", +[0x04] 0,0, "MOVW MSW,%e", /* word */ +[0x06] 0,0, "MOVW %e,MSW", /* word */ +[0x07] 0,0, "INVLPG %e", /* or SWAPGS */ }; +static Optable optab0F01F8[1]= +{ +[0x00] 0,0, "SWAPGS", +}; + +/* 0F71 */ +/* 0F72 */ +/* 0F73 */ + +static Optable optab0FAE[8]= +{ +[0x00] 0,0, "FXSAVE %e", +[0x01] 0,0, "FXRSTOR %e", +[0x02] 0,0, "LDMXCSR %e", +[0x03] 0,0, "STMXCSR %e", +[0x05] 0,0, "LFENCE", +[0x06] 0,0, "MFENCE", +[0x07] 0,0, "SFENCE", +}; + +/* 0F18 */ +/* 0F0D */ + static Optable optab0FBA[8]= { - 0,0, "", /* 0x00 */ - 0,0, "", /* 0x01 */ - 0,0, "", /* 0x02 */ - 0,0, "", /* 0x03 */ - Ib,0, "BT%S %i,%e", /* 0x04 */ - Ib,0, "BTS%S %i,%e", /* 0x05 */ - Ib,0, "BTR%S %i,%e", /* 0x06 */ - Ib,0, "BTC%S %i,%e", /* 0x07 */ +[0x04] Ib,0, "BT%S %i,%e", +[0x05] Ib,0, "BTS%S %i,%e", +[0x06] Ib,0, "BTR%S %i,%e", +[0x07] Ib,0, "BTC%S %i,%e", +}; + +static Optable optab0F0F[256]= +{ +[0x0c] 0,0, "PI2FW %m,%M", +[0x0d] 0,0, "PI2L %m,%M", +[0x1c] 0,0, "PF2IW %m,%M", +[0x1d] 0,0, "PF2IL %m,%M", +[0x8a] 0,0, "PFNACC %m,%M", +[0x8e] 0,0, "PFPNACC %m,%M", +[0x90] 0,0, "PFCMPGE %m,%M", +[0x94] 0,0, "PFMIN %m,%M", +[0x96] 0,0, "PFRCP %m,%M", +[0x97] 0,0, "PFRSQRT %m,%M", +[0x9a] 0,0, "PFSUB %m,%M", +[0x9e] 0,0, "PFADD %m,%M", +[0xa0] 0,0, "PFCMPGT %m,%M", +[0xa4] 0,0, "PFMAX %m,%M", +[0xa6] 0,0, "PFRCPIT1 %m,%M", +[0xa7] 0,0, "PFRSQIT1 %m,%M", +[0xaa] 0,0, "PFSUBR %m,%M", +[0xae] 0,0, "PFACC %m,%M", +[0xb0] 0,0, "PFCMPEQ %m,%M", +[0xb4] 0,0, "PFMUL %m,%M", +[0xb6] 0,0, "PFRCPI2T %m,%M", +[0xb7] 0,0, "PMULHRW %m,%M", +[0xbb] 0,0, "PSWAPL %m,%M", +}; + +static Optable optab0FC7[8]= +{ +[0x01] 0,0, "CMPXCHG8B %e", +}; + +static Optable optab660F71[8]= +{ +[0x02] Ib,0, "PSRLW %i,%X", +[0x04] Ib,0, "PSRAW %i,%X", +[0x06] Ib,0, "PSLLW %i,%X", +}; + +static Optable optab660F72[8]= +{ +[0x02] Ib,0, "PSRLL %i,%X", +[0x04] Ib,0, "PSRAL %i,%X", +[0x06] Ib,0, "PSLLL %i,%X", +}; + +static Optable optab660F73[8]= +{ +[0x02] Ib,0, "PSRLQ %i,%X", +[0x03] Ib,0, "PSRLO %i,%X", +[0x06] Ib,0, "PSLLQ %i,%X", +[0x07] Ib,0, "PSLLO %i,%X", +}; + +static Optable optab660F[256]= +{ +[0x2B] RM,0, "MOVNTPD %x,%e", +[0x2E] RM,0, "UCOMISD %x,%X", +[0x2F] RM,0, "COMISD %x,%X", +[0x5A] RM,0, "CVTPD2PS %x,%X", +[0x5B] RM,0, "CVTPS2PL %x,%X", +[0x6A] RM,0, "PUNPCKHLQ %x,%X", +[0x6B] RM,0, "PACKSSLW %x,%X", +[0x6C] RM,0, "PUNPCKLQDQ %x,%X", +[0x6D] RM,0, "PUNPCKHQDQ %x,%X", +[0x6E] RM,0, "MOV%S %e,%X", +[0x6F] RM,0, "MOVO %x,%X", /* MOVDQA */ +[0x70] RM,Ib, "PSHUFL %i,%x,%X", +[0x71] RMOP,0, optab660F71, +[0x72] RMOP,0, optab660F72, +[0x73] RMOP,0, optab660F73, +[0x7E] RM,0, "MOV%S %X,%e", +[0x7F] RM,0, "MOVO %X,%x", +[0xC4] RM,Ib, "PINSRW %i,%e,%X", +[0xC5] RMR,Ib, "PEXTRW %i,%X,%e", +[0xD4] RM,0, "PADDQ %x,%X", +[0xD5] RM,0, "PMULLW %x,%X", +[0xD6] RM,0, "MOVQ %X,%x", +[0xE6] RM,0, "CVTTPD2PL %x,%X", +[0xE7] RM,0, "MOVNTO %X,%e", +[0xF7] RM,0, "MASKMOVOU %x,%X", +}; + +static Optable optabF20F[256]= +{ +[0x10] RM,0, "MOVSD %x,%X", +[0x11] RM,0, "MOVSD %X,%x", +[0x2A] RM,0, "CVTS%S2SD %e,%X", +[0x2C] RM,0, "CVTTSD2S%S %x,%r", +[0x2D] RM,0, "CVTSD2S%S %x,%r", +[0x5A] RM,0, "CVTSD2SS %x,%X", +[0x6F] RM,0, "MOVOU %x,%X", +[0x70] RM,Ib, "PSHUFLW %i,%x,%X", +[0x7F] RM,0, "MOVOU %X,%x", +[0xD6] RM,0, "MOVQOZX %M,%X", +[0xE6] RM,0, "CVTPD2PL %x,%X", +}; + +static Optable optabF30F[256]= +{ +[0x10] RM,0, "MOVSS %x,%X", +[0x11] RM,0, "MOVSS %X,%x", +[0x2A] RM,0, "CVTS%S2SS %e,%X", +[0x2C] RM,0, "CVTTSS2S%S %x,%r", +[0x2D] RM,0, "CVTSS2S%S %x,%r", +[0x5A] RM,0, "CVTSS2SD %x,%X", +[0x5B] RM,0, "CVTTPS2PL %x,%X", +[0x6F] RM,0, "MOVOU %x,%X", +[0x70] RM,Ib, "PSHUFHW %i,%x,%X", +[0x7E] RM,0, "MOVQOZX %x,%X", +[0x7F] RM,0, "MOVOU %X,%x", +[0xD6] RM,0, "MOVQOZX %m*,%X", +[0xE6] RM,0, "CVTPL2PD %x,%X", }; static Optable optab0F[256]= { - RMOP,0, optab0F00, /* 0x00 */ - RMOP,0, optab0F01, /* 0x01 */ - RM,0, "LAR %e,%r", /* 0x02 */ - RM,0, "LSL %e,%r", /* 0x03 */ - 0,0, "", /* 0x04 */ - 0,0, "", /* 0x05 */ - 0,0, "CLTS", /* 0x06 */ - 0,0, "", /* 0x07 */ - 0,0, "INVD", /* 0x08 */ - 0,0, "WBINVD", /* 0x09 */ - 0,0, "", /* 0x0a */ - 0,0, "", /* 0x0b */ - 0,0, "", /* 0x0c */ - 0,0, "", /* 0x0d */ - 0,0, "", /* 0x0e */ - 0,0, "", /* 0x0f */ - 0,0, "", /* 0x10 */ - 0,0, "", /* 0x11 */ - 0,0, "", /* 0x12 */ - 0,0, "", /* 0x13 */ - 0,0, "", /* 0x14 */ - 0,0, "", /* 0x15 */ - 0,0, "", /* 0x16 */ - 0,0, "", /* 0x17 */ - 0,0, "", /* 0x18 */ - 0,0, "", /* 0x19 */ - 0,0, "", /* 0x1a */ - 0,0, "", /* 0x1b */ - 0,0, "", /* 0x1c */ - 0,0, "", /* 0x1d */ - 0,0, "", /* 0x1e */ - 0,0, "", /* 0x1f */ - RMR,0, "MOVL %C,%e", /* 0x20 */ - RMR,0, "MOVL %D,%e", /* 0x21 */ - RMR,0, "MOVL %e,%C", /* 0x22 */ - RMR,0, "MOVL %e,%D", /* 0x23 */ - RMR,0, "MOVL %T,%e", /* 0x24 */ - 0,0, "", /* 0x25 */ - RMR,0, "MOVL %e,%T", /* 0x26 */ - 0,0, "", /* 0x27 */ - 0,0, "", /* 0x28 */ - 0,0, "", /* 0x29 */ - 0,0, "", /* 0x2a */ - 0,0, "", /* 0x2b */ - 0,0, "", /* 0x2c */ - 0,0, "", /* 0x2d */ - 0,0, "", /* 0x2e */ - 0,0, "", /* 0x2f */ - 0,0, "WRMSR", /* 0x30 */ - 0,0, "RDTSC", /* 0x31 */ - 0,0, "RDMSR", /* 0x32 */ - 0,0, "", /* 0x33 */ - 0,0, "", /* 0x34 */ - 0,0, "", /* 0x35 */ - 0,0, "", /* 0x36 */ - 0,0, "", /* 0x37 */ - 0,0, "", /* 0x38 */ - 0,0, "", /* 0x39 */ - 0,0, "", /* 0x3a */ - 0,0, "", /* 0x3b */ - 0,0, "", /* 0x3c */ - 0,0, "", /* 0x3d */ - 0,0, "", /* 0x3e */ - 0,0, "", /* 0x3f */ - 0,0, "", /* 0x40 */ - 0,0, "", /* 0x41 */ - 0,0, "", /* 0x42 */ - 0,0, "", /* 0x43 */ - 0,0, "", /* 0x44 */ - 0,0, "", /* 0x45 */ - 0,0, "", /* 0x46 */ - 0,0, "", /* 0x47 */ - 0,0, "", /* 0x48 */ - 0,0, "", /* 0x49 */ - 0,0, "", /* 0x4a */ - 0,0, "", /* 0x4b */ - 0,0, "", /* 0x4c */ - 0,0, "", /* 0x4d */ - 0,0, "", /* 0x4e */ - 0,0, "", /* 0x4f */ - 0,0, "", /* 0x50 */ - 0,0, "", /* 0x51 */ - 0,0, "", /* 0x52 */ - 0,0, "", /* 0x53 */ - 0,0, "", /* 0x54 */ - 0,0, "", /* 0x55 */ - 0,0, "", /* 0x56 */ - 0,0, "", /* 0x57 */ - 0,0, "", /* 0x58 */ - 0,0, "", /* 0x59 */ - 0,0, "", /* 0x5a */ - 0,0, "", /* 0x5b */ - 0,0, "", /* 0x5c */ - 0,0, "", /* 0x5d */ - 0,0, "", /* 0x5e */ - 0,0, "", /* 0x5f */ - 0,0, "", /* 0x60 */ - 0,0, "", /* 0x61 */ - 0,0, "", /* 0x62 */ - 0,0, "", /* 0x63 */ - 0,0, "", /* 0x64 */ - 0,0, "", /* 0x65 */ - 0,0, "", /* 0x66 */ - 0,0, "", /* 0x67 */ - 0,0, "", /* 0x68 */ - 0,0, "", /* 0x69 */ - 0,0, "", /* 0x6a */ - 0,0, "", /* 0x6b */ - 0,0, "", /* 0x6c */ - 0,0, "", /* 0x6d */ - 0,0, "", /* 0x6e */ - 0,0, "", /* 0x6f */ - 0,0, "", /* 0x70 */ - 0,0, "", /* 0x71 */ - 0,0, "", /* 0x72 */ - 0,0, "", /* 0x73 */ - 0,0, "", /* 0x74 */ - 0,0, "", /* 0x75 */ - 0,0, "", /* 0x76 */ - 0,0, "", /* 0x77 */ - 0,0, "", /* 0x78 */ - 0,0, "", /* 0x79 */ - 0,0, "", /* 0x7a */ - 0,0, "", /* 0x7b */ - 0,0, "", /* 0x7c */ - 0,0, "", /* 0x7d */ - 0,0, "", /* 0x7e */ - 0,0, "", /* 0x7f */ - Iwds,0, "JOS %p", /* 0x80 */ - Iwds,0, "JOC %p", /* 0x81 */ - Iwds,0, "JCS %p", /* 0x82 */ - Iwds,0, "JCC %p", /* 0x83 */ - Iwds,0, "JEQ %p", /* 0x84 */ - Iwds,0, "JNE %p", /* 0x85 */ - Iwds,0, "JLS %p", /* 0x86 */ - Iwds,0, "JHI %p", /* 0x87 */ - Iwds,0, "JMI %p", /* 0x88 */ - Iwds,0, "JPL %p", /* 0x89 */ - Iwds,0, "JPS %p", /* 0x8a */ - Iwds,0, "JPC %p", /* 0x8b */ - Iwds,0, "JLT %p", /* 0x8c */ - Iwds,0, "JGE %p", /* 0x8d */ - Iwds,0, "JLE %p", /* 0x8e */ - Iwds,0, "JGT %p", /* 0x8f */ - RMB,0, "SETOS %e", /* 0x90 */ - RMB,0, "SETOC %e", /* 0x91 */ - RMB,0, "SETCS %e", /* 0x92 */ - RMB,0, "SETCC %e", /* 0x93 */ - RMB,0, "SETEQ %e", /* 0x94 */ - RMB,0, "SETNE %e", /* 0x95 */ - RMB,0, "SETLS %e", /* 0x96 */ - RMB,0, "SETHI %e", /* 0x97 */ - RMB,0, "SETMI %e", /* 0x98 */ - RMB,0, "SETPL %e", /* 0x99 */ - RMB,0, "SETPS %e", /* 0x9a */ - RMB,0, "SETPC %e", /* 0x9b */ - RMB,0, "SETLT %e", /* 0x9c */ - RMB,0, "SETGE %e", /* 0x9d */ - RMB,0, "SETLE %e", /* 0x9e */ - RMB,0, "SETGT %e", /* 0x9f */ - 0,0, "PUSHL FS", /* 0xa0 */ - 0,0, "POPL FS", /* 0xa1 */ - 0,0, "CPUID", /* 0xa2 */ - RM,0, "BT%S %r,%e", /* 0xa3 */ - RM,Ib, "SHLD%S %r,%i,%e", /* 0xa4 */ - RM,0, "SHLD%S %r,CL,%e", /* 0xa5 */ - 0,0, "", /* 0xa6 */ - 0,0, "", /* 0xa7 */ - 0,0, "PUSHL GS", /* 0xa8 */ - 0,0, "POPL GS", /* 0xa9 */ - 0,0, "", /* 0xaa */ - RM,0, "BTS%S %r,%e", /* 0xab */ - RM,Ib, "SHRD%S %r,%i,%e", /* 0xac */ - RM,0, "SHRD%S %r,CL,%e", /* 0xad */ - 0,0, "", /* 0xae */ - RM,0, "IMUL%S %e,%r", /* 0xaf */ - 0,0, "", /* 0xb0 */ - 0,0, "", /* 0xb1 */ - RMM,0, "LSS %e,%r", /* 0xb2 */ - RM,0, "BTR%S %r,%e", /* 0xb3 */ - RMM,0, "LFS %e,%r", /* 0xb4 */ - RMM,0, "LGS %e,%r", /* 0xb5 */ - RMB,0, "MOVBZX %e,%R", /* 0xb6 */ - RM,0, "MOVWZX %e,%R", /* 0xb7 */ - 0,0, "", /* 0xb8 */ - 0,0, "", /* 0xb9 */ - RMOP,0, optab0FBA, /* 0xba */ - RM,0, "BTC%S %e,%r", /* 0xbb */ - RM,0, "BSF%S %e,%r", /* 0xbc */ - RM,0, "BSR%S %e,%r", /* 0xbd */ - RMB,0, "MOVBSX %e,%R", /* 0xbe */ - RM,0, "MOVWSX %e,%R", /* 0xbf */ +[0x00] RMOP,0, optab0F00, +[0x01] RMOP,0, optab0F01, +[0x02] RM,0, "LAR %e,%r", +[0x03] RM,0, "LSL %e,%r", +[0x05] 0,0, "SYSCALL", +[0x06] 0,0, "CLTS", +[0x07] 0,0, "SYSRET", +[0x08] 0,0, "INVD", +[0x09] 0,0, "WBINVD", +[0x0B] 0,0, "UD2", +[0x0F] RM,AUX, optab0F0F, /* 3DNow! */ +[0x10] RM,0, "MOVU%s %x,%X", +[0x11] RM,0, "MOVU%s %X,%x", +[0x12] RM,0, "MOV[H]L%s %x,%X", /* TO DO: H if source is XMM */ +[0x13] RM,0, "MOVL%s %X,%e", +[0x14] RM,0, "UNPCKL%s %x,%X", +[0x15] RM,0, "UNPCKH%s %x,%X", +[0x16] RM,0, "MOV[L]H%s %x,%X", /* TO DO: L if source is XMM */ +[0x17] RM,0, "MOVH%s %X,%x", +[0x20] RMR,0, "MOVL %C,%e", +[0x21] RMR,0, "MOVL %D,%e", +[0x22] RMR,0, "MOVL %e,%C", +[0x23] RMR,0, "MOVL %e,%D", +[0x24] RMR,0, "MOVL %T,%e", +[0x26] RMR,0, "MOVL %e,%T", +[0x28] RM,0, "MOVA%s %x,%X", +[0x29] RM,0, "MOVA%s %X,%x", +[0x2A] RM,0, "CVTPL2%s %m*,%X", +[0x2B] RM,0, "MOVNT%s %X,%e", +[0x2C] RM,0, "CVTT%s2PL %x,%M", +[0x2D] RM,0, "CVT%s2PL %x,%M", +[0x2E] RM,0, "UCOMISS %x,%X", +[0x2F] RM,0, "COMISS %x,%X", +[0x30] 0,0, "WRMSR", +[0x31] 0,0, "RDTSC", +[0x32] 0,0, "RDMSR", +[0x33] 0,0, "RDPMC", +[0x42] RM,0, "CMOVC %e,%r", /* CF */ +[0x43] RM,0, "CMOVNC %e,%r", /* ¬ CF */ +[0x44] RM,0, "CMOVZ %e,%r", /* ZF */ +[0x45] RM,0, "CMOVNZ %e,%r", /* ¬ ZF */ +[0x46] RM,0, "CMOVBE %e,%r", /* CF ∨ ZF */ +[0x47] RM,0, "CMOVA %e,%r", /* ¬CF ∧ ¬ZF */ +[0x48] RM,0, "CMOVS %e,%r", /* SF */ +[0x49] RM,0, "CMOVNS %e,%r", /* ¬ SF */ +[0x4A] RM,0, "CMOVP %e,%r", /* PF */ +[0x4B] RM,0, "CMOVNP %e,%r", /* ¬ PF */ +[0x4C] RM,0, "CMOVLT %e,%r", /* LT ≡ OF ≠SF */ +[0x4D] RM,0, "CMOVGE %e,%r", /* GE ≡ ZF ∨ SF */ +[0x4E] RM,0, "CMOVLE %e,%r", /* LE ≡ ZF ∨ LT */ +[0x4F] RM,0, "CMOVGT %e,%r", /* GT ≡ ¬ZF ∧ GE */ +[0x50] RM,0, "MOVMSK%s %X,%r", /* TO DO: check */ +[0x51] RM,0, "SQRT%s %x,%X", +[0x52] RM,0, "RSQRT%s %x,%X", +[0x53] RM,0, "RCP%s %x,%X", +[0x54] RM,0, "AND%s %x,%X", +[0x55] RM,0, "ANDN%s %x,%X", +[0x56] RM,0, "OR%s %x,%X", /* TO DO: S/D */ +[0x57] RM,0, "XOR%s %x,%X", /* S/D */ +[0x58] RM,0, "ADD%s %x,%X", /* S/P S/D */ +[0x59] RM,0, "MUL%s %x,%X", +[0x5A] RM,0, "CVTPS2PD %x,%X", +[0x5B] RM,0, "CVTPL2PS %x,%X", +[0x5C] RM,0, "SUB%s %x,%X", +[0x5D] RM,0, "MIN%s %x,%X", +[0x5E] RM,0, "DIV%s %x,%X", /* TO DO: S/P S/D */ +[0x5F] RM,0, "MAX%s %x,%X", +[0x60] RM,0, "PUNPCKLBW %m,%M", +[0x61] RM,0, "PUNPCKLWL %m,%M", +[0x62] RM,0, "PUNPCKLLQ %m,%M", +[0x63] RM,0, "PACKSSWB %m,%M", +[0x64] RM,0, "PCMPGTB %m,%M", +[0x65] RM,0, "PCMPGTW %m,%M", +[0x66] RM,0, "PCMPGTL %m,%M", +[0x67] RM,0, "PACKUSWB %m,%M", +[0x68] RM,0, "PUNPCKHBW %m,%M", +[0x69] RM,0, "PUNPCKHWL %m,%M", +[0x6A] RM,0, "PUNPCKHLQ %m,%M", +[0x6B] RM,0, "PACKSSLW %m,%M", +[0x6E] RM,0, "MOV%S %e,%M", +[0x6F] RM,0, "MOVQ %m,%M", +[0x70] RM,Ib, "PSHUFW %i,%m,%M", +[0x74] RM,0, "PCMPEQB %m,%M", +[0x75] RM,0, "PCMPEQW %m,%M", +[0x76] RM,0, "PCMPEQL %m,%M", +[0x7E] RM,0, "MOV%S %M,%e", +[0x7F] RM,0, "MOVQ %M,%m", +[0xAE] RMOP,0, optab0FAE, +[0xAA] 0,0, "RSM", +[0xB0] RM,0, "CMPXCHGB %r,%e", +[0xB1] RM,0, "CMPXCHG%S %r,%e", +[0xC0] RMB,0, "XADDB %r,%e", +[0xC1] RM,0, "XADD%S %r,%e", +[0xC2] RM,Ib, "CMP%s %i,%x,%X", +[0xC3] RM,0, "MOVNTI%S %r,%e", +[0xC6] RM,Ib, "SHUF%s %i,%x,%X", +[0xC8] 0,0, "BSWAP AX", +[0xC9] 0,0, "BSWAP CX", +[0xCA] 0,0, "BSWAP DX", +[0xCB] 0,0, "BSWAP BX", +[0xCC] 0,0, "BSWAP SP", +[0xCD] 0,0, "BSWAP BP", +[0xCE] 0,0, "BSWAP SI", +[0xCF] 0,0, "BSWAP DI", +[0xD1] RM,0, "PSRLW %m,%M", +[0xD2] RM,0, "PSRLL %m,%M", +[0xD3] RM,0, "PSRLQ %m,%M", +[0xD5] RM,0, "PMULLW %m,%M", +[0xD6] RM,0, "MOVQOZX %m*,%X", +[0xD7] RM,0, "PMOVMSKB %m,%r", +[0xD8] RM,0, "PSUBUSB %m,%M", +[0xD9] RM,0, "PSUBUSW %m,%M", +[0xDA] RM,0, "PMINUB %m,%M", +[0xDB] RM,0, "PAND %m,%M", +[0xDC] RM,0, "PADDUSB %m,%M", +[0xDD] RM,0, "PADDUSW %m,%M", +[0xDE] RM,0, "PMAXUB %m,%M", +[0xDF] RM,0, "PANDN %m,%M", +[0xE0] RM,0, "PAVGB %m,%M", +[0xE1] RM,0, "PSRAW %m,%M", +[0xE2] RM,0, "PSRAL %m,%M", +[0xE3] RM,0, "PAVGW %m,%M", +[0xE4] RM,0, "PMULHUW %m,%M", +[0xE5] RM,0, "PMULHW %m,%M", +[0xE7] RM,0, "MOVNTQ %M,%e", +[0xE8] RM,0, "PSUBSB %m,%M", +[0xE9] RM,0, "PSUBSW %m,%M", +[0xEA] RM,0, "PMINSW %m,%M", +[0xEB] RM,0, "POR %m,%M", +[0xEC] RM,0, "PADDSB %m,%M", +[0xED] RM,0, "PADDSW %m,%M", +[0xEE] RM,0, "PMAXSW %m,%M", +[0xEF] RM,0, "PXOR %m,%M", +[0xF1] RM,0, "PSLLW %m,%M", +[0xF2] RM,0, "PSLLL %m,%M", +[0xF3] RM,0, "PSLLQ %m,%M", +[0xF4] RM,0, "PMULULQ %m,%M", +[0xF5] RM,0, "PMADDWL %m,%M", +[0xF6] RM,0, "PSADBW %m,%M", +[0xF7] RMR,0, "MASKMOVQ %m,%M", +[0xF8] RM,0, "PSUBB %m,%M", +[0xF9] RM,0, "PSUBW %m,%M", +[0xFA] RM,0, "PSUBL %m,%M", +[0xFC] RM,0, "PADDB %m,%M", +[0xFD] RM,0, "PADDW %m,%M", +[0xFE] RM,0, "PADDL %m,%M", + +[0x80] Iwds,0, "JOS %p", +[0x81] Iwds,0, "JOC %p", +[0x82] Iwds,0, "JCS %p", +[0x83] Iwds,0, "JCC %p", +[0x84] Iwds,0, "JEQ %p", +[0x85] Iwds,0, "JNE %p", +[0x86] Iwds,0, "JLS %p", +[0x87] Iwds,0, "JHI %p", +[0x88] Iwds,0, "JMI %p", +[0x89] Iwds,0, "JPL %p", +[0x8a] Iwds,0, "JPS %p", +[0x8b] Iwds,0, "JPC %p", +[0x8c] Iwds,0, "JLT %p", +[0x8d] Iwds,0, "JGE %p", +[0x8e] Iwds,0, "JLE %p", +[0x8f] Iwds,0, "JGT %p", +[0x90] RMB,0, "SETOS %e", +[0x91] RMB,0, "SETOC %e", +[0x92] RMB,0, "SETCS %e", +[0x93] RMB,0, "SETCC %e", +[0x94] RMB,0, "SETEQ %e", +[0x95] RMB,0, "SETNE %e", +[0x96] RMB,0, "SETLS %e", +[0x97] RMB,0, "SETHI %e", +[0x98] RMB,0, "SETMI %e", +[0x99] RMB,0, "SETPL %e", +[0x9a] RMB,0, "SETPS %e", +[0x9b] RMB,0, "SETPC %e", +[0x9c] RMB,0, "SETLT %e", +[0x9d] RMB,0, "SETGE %e", +[0x9e] RMB,0, "SETLE %e", +[0x9f] RMB,0, "SETGT %e", +[0xa0] 0,0, "PUSHL FS", +[0xa1] 0,0, "POPL FS", +[0xa2] 0,0, "CPUID", +[0xa3] RM,0, "BT%S %r,%e", +[0xa4] RM,Ib, "SHLD%S %r,%i,%e", +[0xa5] RM,0, "SHLD%S %r,CL,%e", +[0xa8] 0,0, "PUSHL GS", +[0xa9] 0,0, "POPL GS", +[0xab] RM,0, "BTS%S %r,%e", +[0xac] RM,Ib, "SHRD%S %r,%i,%e", +[0xad] RM,0, "SHRD%S %r,CL,%e", +[0xaf] RM,0, "IMUL%S %e,%r", +[0xb2] RMM,0, "LSS %e,%r", +[0xb3] RM,0, "BTR%S %r,%e", +[0xb4] RMM,0, "LFS %e,%r", +[0xb5] RMM,0, "LGS %e,%r", +[0xb6] RMB,0, "MOVBZX %e,%R", +[0xb7] RM,0, "MOVWZX %e,%R", +[0xba] RMOP,0, optab0FBA, +[0xbb] RM,0, "BTC%S %e,%r", +[0xbc] RM,0, "BSF%S %e,%r", +[0xbd] RM,0, "BSR%S %e,%r", +[0xbe] RMB,0, "MOVBSX %e,%R", +[0xbf] RM,0, "MOVWSX %e,%R", +[0xc7] RMOP,0, optab0FC7, }; static Optable optab80[8]= { - Ib,0, "ADDB %i,%e", /* 0x00 */ - Ib,0, "ORB %i,%e", /* 0x01 */ - Ib,0, "ADCB %i,%e", /* 0x02 */ - Ib,0, "SBBB %i,%e", /* 0x03 */ - Ib,0, "ANDB %i,%e", /* 0x04 */ - Ib,0, "SUBB %i,%e", /* 0x05 */ - Ib,0, "XORB %i,%e", /* 0x06 */ - Ib,0, "CMPB %e,%i", /* 0x07 */ +[0x00] Ib,0, "ADDB %i,%e", +[0x01] Ib,0, "ORB %i,%e", +[0x02] Ib,0, "ADCB %i,%e", +[0x03] Ib,0, "SBBB %i,%e", +[0x04] Ib,0, "ANDB %i,%e", +[0x05] Ib,0, "SUBB %i,%e", +[0x06] Ib,0, "XORB %i,%e", +[0x07] Ib,0, "CMPB %e,%i", }; static Optable optab81[8]= { - Iwd,0, "ADD%S %i,%e", /* 0x00 */ - Iwd,0, "OR%S %i,%e", /* 0x01 */ - Iwd,0, "ADC%S %i,%e", /* 0x02 */ - Iwd,0, "SBB%S %i,%e", /* 0x03 */ - Iwd,0, "AND%S %i,%e", /* 0x04 */ - Iwd,0, "SUB%S %i,%e", /* 0x05 */ - Iwd,0, "XOR%S %i,%e", /* 0x06 */ - Iwd,0, "CMP%S %e,%i", /* 0x07 */ +[0x00] Iwd,0, "ADD%S %i,%e", +[0x01] Iwd,0, "OR%S %i,%e", +[0x02] Iwd,0, "ADC%S %i,%e", +[0x03] Iwd,0, "SBB%S %i,%e", +[0x04] Iwd,0, "AND%S %i,%e", +[0x05] Iwd,0, "SUB%S %i,%e", +[0x06] Iwd,0, "XOR%S %i,%e", +[0x07] Iwd,0, "CMP%S %e,%i", }; static Optable optab83[8]= { - Ibs,0, "ADD%S %i,%e", /* 0x00 */ - Ibs,0, "OR%S %i,%e", /* 0x01 */ - Ibs,0, "ADC%S %i,%e", /* 0x02 */ - Ibs,0, "SBB%S %i,%e", /* 0x03 */ - Ibs,0, "AND%S %i,%e", /* 0x04 */ - Ibs,0, "SUB%S %i,%e", /* 0x05 */ - Ibs,0, "XOR%S %i,%e", /* 0x06 */ - Ibs,0, "CMP%S %e,%i", /* 0x07 */ +[0x00] Ibs,0, "ADD%S %i,%e", +[0x01] Ibs,0, "OR%S %i,%e", +[0x02] Ibs,0, "ADC%S %i,%e", +[0x03] Ibs,0, "SBB%S %i,%e", +[0x04] Ibs,0, "AND%S %i,%e", +[0x05] Ibs,0, "SUB%S %i,%e", +[0x06] Ibs,0, "XOR%S %i,%e", +[0x07] Ibs,0, "CMP%S %e,%i", }; static Optable optabC0[8] = { - Ib,0, "ROLB %i,%e", /* 0x00 */ - Ib,0, "RORB %i,%e", /* 0x01 */ - Ib,0, "RCLB %i,%e", /* 0x02 */ - Ib,0, "RCRB %i,%e", /* 0x03 */ - Ib,0, "SHLB %i,%e", /* 0x04 */ - Ib,0, "SHRB %i,%e", /* 0x05 */ - 0,0, "", /* 0x06 */ - Ib,0, "SARB %i,%e", /* 0x07 */ +[0x00] Ib,0, "ROLB %i,%e", +[0x01] Ib,0, "RORB %i,%e", +[0x02] Ib,0, "RCLB %i,%e", +[0x03] Ib,0, "RCRB %i,%e", +[0x04] Ib,0, "SHLB %i,%e", +[0x05] Ib,0, "SHRB %i,%e", +[0x07] Ib,0, "SARB %i,%e", }; static Optable optabC1[8] = { - Ib,0, "ROL%S %i,%e", /* 0x00 */ - Ib,0, "ROR%S %i,%e", /* 0x01 */ - Ib,0, "RCL%S %i,%e", /* 0x02 */ - Ib,0, "RCR%S %i,%e", /* 0x03 */ - Ib,0, "SHL%S %i,%e", /* 0x04 */ - Ib,0, "SHR%S %i,%e", /* 0x05 */ - 0,0, "", /* 0x06 */ - Ib,0, "SAR%S %i,%e", /* 0x07 */ +[0x00] Ib,0, "ROL%S %i,%e", +[0x01] Ib,0, "ROR%S %i,%e", +[0x02] Ib,0, "RCL%S %i,%e", +[0x03] Ib,0, "RCR%S %i,%e", +[0x04] Ib,0, "SHL%S %i,%e", +[0x05] Ib,0, "SHR%S %i,%e", +[0x07] Ib,0, "SAR%S %i,%e", }; static Optable optabD0[8] = { - 0,0, "ROLB %e", /* 0x00 */ - 0,0, "RORB %e", /* 0x01 */ - 0,0, "RCLB %e", /* 0x02 */ - 0,0, "RCRB %e", /* 0x03 */ - 0,0, "SHLB %e", /* 0x04 */ - 0,0, "SHRB %e", /* 0x05 */ - 0,0, "", /* 0x06 */ - 0,0, "SARB %e", /* 0x07 */ +[0x00] 0,0, "ROLB %e", +[0x01] 0,0, "RORB %e", +[0x02] 0,0, "RCLB %e", +[0x03] 0,0, "RCRB %e", +[0x04] 0,0, "SHLB %e", +[0x05] 0,0, "SHRB %e", +[0x07] 0,0, "SARB %e", }; static Optable optabD1[8] = { - 0,0, "ROL%S %e", /* 0x00 */ - 0,0, "ROR%S %e", /* 0x01 */ - 0,0, "RCL%S %e", /* 0x02 */ - 0,0, "RCR%S %e", /* 0x03 */ - 0,0, "SHL%S %e", /* 0x04 */ - 0,0, "SHR%S %e", /* 0x05 */ - 0,0, "", /* 0x06 */ - 0,0, "SAR%S %e", /* 0x07 */ +[0x00] 0,0, "ROL%S %e", +[0x01] 0,0, "ROR%S %e", +[0x02] 0,0, "RCL%S %e", +[0x03] 0,0, "RCR%S %e", +[0x04] 0,0, "SHL%S %e", +[0x05] 0,0, "SHR%S %e", +[0x07] 0,0, "SAR%S %e", }; static Optable optabD2[8] = { - 0,0, "ROLB CL,%e", /* 0x00 */ - 0,0, "RORB CL,%e", /* 0x01 */ - 0,0, "RCLB CL,%e", /* 0x02 */ - 0,0, "RCRB CL,%e", /* 0x03 */ - 0,0, "SHLB CL,%e", /* 0x04 */ - 0,0, "SHRB CL,%e", /* 0x05 */ - 0,0, "", /* 0x06 */ - 0,0, "SARB CL,%e", /* 0x07 */ +[0x00] 0,0, "ROLB CL,%e", +[0x01] 0,0, "RORB CL,%e", +[0x02] 0,0, "RCLB CL,%e", +[0x03] 0,0, "RCRB CL,%e", +[0x04] 0,0, "SHLB CL,%e", +[0x05] 0,0, "SHRB CL,%e", +[0x07] 0,0, "SARB CL,%e", }; static Optable optabD3[8] = { - 0,0, "ROL%S CL,%e", /* 0x00 */ - 0,0, "ROR%S CL,%e", /* 0x01 */ - 0,0, "RCL%S CL,%e", /* 0x02 */ - 0,0, "RCR%S CL,%e", /* 0x03 */ - 0,0, "SHL%S CL,%e", /* 0x04 */ - 0,0, "SHR%S CL,%e", /* 0x05 */ - 0,0, "", /* 0x06 */ - 0,0, "SAR%S CL,%e", /* 0x07 */ +[0x00] 0,0, "ROL%S CL,%e", +[0x01] 0,0, "ROR%S CL,%e", +[0x02] 0,0, "RCL%S CL,%e", +[0x03] 0,0, "RCR%S CL,%e", +[0x04] 0,0, "SHL%S CL,%e", +[0x05] 0,0, "SHR%S CL,%e", +[0x07] 0,0, "SAR%S CL,%e", }; static Optable optabD8[8+8] = { - 0,0, "FADDF %e,F0", /* 0x00 */ - 0,0, "FMULF %e,F0", /* 0x01 */ - 0,0, "FCOMF %e,F0", /* 0x02 */ - 0,0, "FCOMFP %e,F0", /* 0x03 */ - 0,0, "FSUBF %e,F0", /* 0x04 */ - 0,0, "FSUBRF %e,F0", /* 0x05 */ - 0,0, "FDIVF %e,F0", /* 0x06 */ - 0,0, "FDIVRF %e,F0", /* 0x07 */ - 0,0, "FADDD %f,F0", /* 0x08 */ - 0,0, "FMULD %f,F0", /* 0x09 */ - 0,0, "FCOMD %f,F0", /* 0x0a */ - 0,0, "FCOMPD %f,F0", /* 0x0b */ - 0,0, "FSUBD %f,F0", /* 0x0c */ - 0,0, "FSUBRD %f,F0", /* 0x0d */ - 0,0, "FDIVD %f,F0", /* 0x0e */ - 0,0, "FDIVRD %f,F0", /* 0x0f */ +[0x00] 0,0, "FADDF %e,F0", +[0x01] 0,0, "FMULF %e,F0", +[0x02] 0,0, "FCOMF %e,F0", +[0x03] 0,0, "FCOMFP %e,F0", +[0x04] 0,0, "FSUBF %e,F0", +[0x05] 0,0, "FSUBRF %e,F0", +[0x06] 0,0, "FDIVF %e,F0", +[0x07] 0,0, "FDIVRF %e,F0", +[0x08] 0,0, "FADDD %f,F0", +[0x09] 0,0, "FMULD %f,F0", +[0x0a] 0,0, "FCOMD %f,F0", +[0x0b] 0,0, "FCOMPD %f,F0", +[0x0c] 0,0, "FSUBD %f,F0", +[0x0d] 0,0, "FSUBRD %f,F0", +[0x0e] 0,0, "FDIVD %f,F0", +[0x0f] 0,0, "FDIVRD %f,F0", }; /* * optabD9 and optabDB use the following encoding: @@ -623,527 +786,449 @@ static Optable optabD8[8+8] = */ static Optable optabD9[64+8] = { - 0,0, "FMOVF %e,F0", /* 0x00 */ - 0,0, "", /* 0x01 */ - 0,0, "FMOVF F0,%e", /* 0x02 */ - 0,0, "FMOVFP F0,%e", /* 0x03 */ - 0,0, "FLDENV%S %e", /* 0x04 */ - 0,0, "FLDCW %e", /* 0x05 */ - 0,0, "FSTENV%S %e", /* 0x06 */ - 0,0, "FSTCW %e", /* 0x07 */ - 0,0, "FMOVD F0,F0", /* 0x08 */ /* Mod R/M = 11xx xxxx*/ - 0,0, "FMOVD F1,F0", /* 0x09 */ - 0,0, "FMOVD F2,F0", /* 0x0a */ - 0,0, "FMOVD F3,F0", /* 0x0b */ - 0,0, "FMOVD F4,F0", /* 0x0c */ - 0,0, "FMOVD F5,F0", /* 0x0d */ - 0,0, "FMOVD F6,F0", /* 0x0e */ - 0,0, "FMOVD F7,F0", /* 0x0f */ - 0,0, "FXCHD F0,F0", /* 0x10 */ - 0,0, "FXCHD F1,F0", /* 0x11 */ - 0,0, "FXCHD F2,F0", /* 0x12 */ - 0,0, "FXCHD F3,F0", /* 0x13 */ - 0,0, "FXCHD F4,F0", /* 0x14 */ - 0,0, "FXCHD F5,F0", /* 0x15 */ - 0,0, "FXCHD F6,F0", /* 0x16 */ - 0,0, "FXCHD F7,F0", /* 0x17 */ - 0,0, "FNOP", /* 0x18 */ - 0,0, "", /* 0x19 */ - 0,0, "", /* 0x1a */ - 0,0, "", /* 0x1b */ - 0,0, "", /* 0x1c */ - 0,0, "", /* 0x1d */ - 0,0, "", /* 0x1e */ - 0,0, "", /* 0x1f */ - 0,0, "", /* 0x20 */ - 0,0, "", /* 0x21 */ - 0,0, "", /* 0x22 */ - 0,0, "", /* 0x23 */ - 0,0, "", /* 0x24 */ - 0,0, "", /* 0x25 */ - 0,0, "", /* 0x26 */ - 0,0, "", /* 0x27 */ - 0,0, "FCHS", /* 0x28 */ - 0,0, "FABS", /* 0x29 */ - 0,0, "", /* 0x2a */ - 0,0, "", /* 0x2b */ - 0,0, "FTST", /* 0x2c */ - 0,0, "FXAM", /* 0x2d */ - 0,0, "", /* 0x2e */ - 0,0, "", /* 0x2f */ - 0,0, "FLD1", /* 0x30 */ - 0,0, "FLDL2T", /* 0x31 */ - 0,0, "FLDL2E", /* 0x32 */ - 0,0, "FLDPI", /* 0x33 */ - 0,0, "FLDLG2", /* 0x34 */ - 0,0, "FLDLN2", /* 0x35 */ - 0,0, "FLDZ", /* 0x36 */ - 0,0, "", /* 0x37 */ - 0,0, "F2XM1", /* 0x38 */ - 0,0, "FYL2X", /* 0x39 */ - 0,0, "FPTAN", /* 0x3a */ - 0,0, "FPATAN", /* 0x3b */ - 0,0, "FXTRACT", /* 0x3c */ - 0,0, "FPREM1", /* 0x3d */ - 0,0, "FDECSTP", /* 0x3e */ - 0,0, "FNCSTP", /* 0x3f */ - 0,0, "FPREM", /* 0x40 */ - 0,0, "FYL2XP1", /* 0x41 */ - 0,0, "FSQRT", /* 0x42 */ - 0,0, "FSINCOS", /* 0x43 */ - 0,0, "FRNDINT", /* 0x44 */ - 0,0, "FSCALE", /* 0x45 */ - 0,0, "FSIN", /* 0x46 */ - 0,0, "FCOS", /* 0x47 */ +[0x00] 0,0, "FMOVF %e,F0", +[0x02] 0,0, "FMOVF F0,%e", +[0x03] 0,0, "FMOVFP F0,%e", +[0x04] 0,0, "FLDENV%S %e", +[0x05] 0,0, "FLDCW %e", +[0x06] 0,0, "FSTENV%S %e", +[0x07] 0,0, "FSTCW %e", +[0x08] 0,0, "FMOVD F0,F0", /* Mod R/M = 11xx xxxx*/ +[0x09] 0,0, "FMOVD F1,F0", +[0x0a] 0,0, "FMOVD F2,F0", +[0x0b] 0,0, "FMOVD F3,F0", +[0x0c] 0,0, "FMOVD F4,F0", +[0x0d] 0,0, "FMOVD F5,F0", +[0x0e] 0,0, "FMOVD F6,F0", +[0x0f] 0,0, "FMOVD F7,F0", +[0x10] 0,0, "FXCHD F0,F0", +[0x11] 0,0, "FXCHD F1,F0", +[0x12] 0,0, "FXCHD F2,F0", +[0x13] 0,0, "FXCHD F3,F0", +[0x14] 0,0, "FXCHD F4,F0", +[0x15] 0,0, "FXCHD F5,F0", +[0x16] 0,0, "FXCHD F6,F0", +[0x17] 0,0, "FXCHD F7,F0", +[0x18] 0,0, "FNOP", +[0x28] 0,0, "FCHS", +[0x29] 0,0, "FABS", +[0x2c] 0,0, "FTST", +[0x2d] 0,0, "FXAM", +[0x30] 0,0, "FLD1", +[0x31] 0,0, "FLDL2T", +[0x32] 0,0, "FLDL2E", +[0x33] 0,0, "FLDPI", +[0x34] 0,0, "FLDLG2", +[0x35] 0,0, "FLDLN2", +[0x36] 0,0, "FLDZ", +[0x38] 0,0, "F2XM1", +[0x39] 0,0, "FYL2X", +[0x3a] 0,0, "FPTAN", +[0x3b] 0,0, "FPATAN", +[0x3c] 0,0, "FXTRACT", +[0x3d] 0,0, "FPREM1", +[0x3e] 0,0, "FDECSTP", +[0x3f] 0,0, "FNCSTP", +[0x40] 0,0, "FPREM", +[0x41] 0,0, "FYL2XP1", +[0x42] 0,0, "FSQRT", +[0x43] 0,0, "FSINCOS", +[0x44] 0,0, "FRNDINT", +[0x45] 0,0, "FSCALE", +[0x46] 0,0, "FSIN", +[0x47] 0,0, "FCOS", }; static Optable optabDA[8+8] = { - 0,0, "FADDL %e,F0", /* 0x00 */ - 0,0, "FMULL %e,F0", /* 0x01 */ - 0,0, "FCOML %e,F0", /* 0x02 */ - 0,0, "FCOMLP %e,F0", /* 0x03 */ - 0,0, "FSUBL %e,F0", /* 0x04 */ - 0,0, "FSUBRL %e,F0", /* 0x05 */ - 0,0, "FDIVL %e,F0", /* 0x06 */ - 0,0, "FDIVRL %e,F0", /* 0x07 */ - 0,0, "", /* 0x08 */ - 0,0, "", /* 0x09 */ - 0,0, "", /* 0x0a */ - 0,0, "", /* 0x0b */ - 0,0, "", /* 0x0c */ - R1,0, "FUCOMPP", /* 0x0d */ +[0x00] 0,0, "FADDL %e,F0", +[0x01] 0,0, "FMULL %e,F0", +[0x02] 0,0, "FCOML %e,F0", +[0x03] 0,0, "FCOMLP %e,F0", +[0x04] 0,0, "FSUBL %e,F0", +[0x05] 0,0, "FSUBRL %e,F0", +[0x06] 0,0, "FDIVL %e,F0", +[0x07] 0,0, "FDIVRL %e,F0", +[0x0d] R1,0, "FUCOMPP", }; static Optable optabDB[8+64] = { - 0,0, "FMOVL %e,F0", /* 0x00 */ - 0,0, "", /* 0x01 */ - 0,0, "FMOVL F0,%e", /* 0x02 */ - 0,0, "FMOVLP F0,%e", /* 0x03 */ - 0,0, "", /* 0x04 */ - 0,0, "FMOVX %e,F0", /* 0x05 */ - 0,0, "", /* 0x06 */ - 0,0, "FMOVXP F0,%e", /* 0x07 */ - 0,0, "", /* 0x08 */ - 0,0, "", /* 0x09 */ - 0,0, "", /* 0x0a */ - 0,0, "", /* 0x0b */ - 0,0, "", /* 0x0c */ - 0,0, "", /* 0x0d */ - 0,0, "", /* 0x0e */ - 0,0, "", /* 0x0f */ - 0,0, "", /* 0x10 */ - 0,0, "", /* 0x11 */ - 0,0, "", /* 0x12 */ - 0,0, "", /* 0x13 */ - 0,0, "", /* 0x14 */ - 0,0, "", /* 0x15 */ - 0,0, "", /* 0x16 */ - 0,0, "", /* 0x17 */ - 0,0, "", /* 0x18 */ - 0,0, "", /* 0x19 */ - 0,0, "", /* 0x1a */ - 0,0, "", /* 0x1b */ - 0,0, "", /* 0x1c */ - 0,0, "", /* 0x1d */ - 0,0, "", /* 0x1e */ - 0,0, "", /* 0x1f */ - 0,0, "", /* 0x20 */ - 0,0, "", /* 0x21 */ - 0,0, "", /* 0x22 */ - 0,0, "", /* 0x23 */ - 0,0, "", /* 0x24 */ - 0,0, "", /* 0x25 */ - 0,0, "", /* 0x26 */ - 0,0, "", /* 0x27 */ - 0,0, "", /* 0x28 */ - 0,0, "", /* 0x29 */ - 0,0, "FCLEX", /* 0x2a */ - 0,0, "FINIT", /* 0x2b */ +[0x00] 0,0, "FMOVL %e,F0", +[0x02] 0,0, "FMOVL F0,%e", +[0x03] 0,0, "FMOVLP F0,%e", +[0x05] 0,0, "FMOVX %e,F0", +[0x07] 0,0, "FMOVXP F0,%e", +[0x2a] 0,0, "FCLEX", +[0x2b] 0,0, "FINIT", }; static Optable optabDC[8+8] = { - 0,0, "FADDD %e,F0", /* 0x00 */ - 0,0, "FMULD %e,F0", /* 0x01 */ - 0,0, "FCOMD %e,F0", /* 0x02 */ - 0,0, "FCOMDP %e,F0", /* 0x03 */ - 0,0, "FSUBD %e,F0", /* 0x04 */ - 0,0, "FSUBRD %e,F0", /* 0x05 */ - 0,0, "FDIVD %e,F0", /* 0x06 */ - 0,0, "FDIVRD %e,F0", /* 0x07 */ - 0,0, "FADDD F0,%f", /* 0x08 */ - 0,0, "FMULD F0,%f", /* 0x09 */ - 0,0, "", /* 0x0a */ - 0,0, "", /* 0x0b */ - 0,0, "FSUBRD F0,%f", /* 0x0c */ - 0,0, "FSUBD F0,%f", /* 0x0d */ - 0,0, "FDIVRD F0,%f", /* 0x0e */ - 0,0, "FDIVD F0,%f", /* 0x0f */ +[0x00] 0,0, "FADDD %e,F0", +[0x01] 0,0, "FMULD %e,F0", +[0x02] 0,0, "FCOMD %e,F0", +[0x03] 0,0, "FCOMDP %e,F0", +[0x04] 0,0, "FSUBD %e,F0", +[0x05] 0,0, "FSUBRD %e,F0", +[0x06] 0,0, "FDIVD %e,F0", +[0x07] 0,0, "FDIVRD %e,F0", +[0x08] 0,0, "FADDD F0,%f", +[0x09] 0,0, "FMULD F0,%f", +[0x0c] 0,0, "FSUBRD F0,%f", +[0x0d] 0,0, "FSUBD F0,%f", +[0x0e] 0,0, "FDIVRD F0,%f", +[0x0f] 0,0, "FDIVD F0,%f", }; static Optable optabDD[8+8] = { - 0,0, "FMOVD %e,F0", /* 0x00 */ - 0,0, "", /* 0x01 */ - 0,0, "FMOVD F0,%e", /* 0x02 */ - 0,0, "FMOVDP F0,%e", /* 0x03 */ - 0,0, "FRSTOR%S %e", /* 0x04 */ - 0,0, "", /* 0x05 */ - 0,0, "FSAVE%S %e", /* 0x06 */ - 0,0, "FSTSW %e", /* 0x07 */ - 0,0, "FFREED %f", /* 0x08 */ - 0,0, "", /* 0x09 */ - 0,0, "FMOVD %f,F0", /* 0x0a */ - 0,0, "FMOVDP %f,F0", /* 0x0b */ - 0,0, "FUCOMD %f,F0", /* 0x0c */ - 0,0, "FUCOMDP %f,F0", /* 0x0d */ +[0x00] 0,0, "FMOVD %e,F0", +[0x02] 0,0, "FMOVD F0,%e", +[0x03] 0,0, "FMOVDP F0,%e", +[0x04] 0,0, "FRSTOR%S %e", +[0x06] 0,0, "FSAVE%S %e", +[0x07] 0,0, "FSTSW %e", +[0x08] 0,0, "FFREED %f", +[0x0a] 0,0, "FMOVD %f,F0", +[0x0b] 0,0, "FMOVDP %f,F0", +[0x0c] 0,0, "FUCOMD %f,F0", +[0x0d] 0,0, "FUCOMDP %f,F0", }; static Optable optabDE[8+8] = { - 0,0, "FADDW %e,F0", /* 0x00 */ - 0,0, "FMULW %e,F0", /* 0x01 */ - 0,0, "FCOMW %e,F0", /* 0x02 */ - 0,0, "FCOMWP %e,F0", /* 0x03 */ - 0,0, "FSUBW %e,F0", /* 0x04 */ - 0,0, "FSUBRW %e,F0", /* 0x05 */ - 0,0, "FDIVW %e,F0", /* 0x06 */ - 0,0, "FDIVRW %e,F0", /* 0x07 */ - 0,0, "FADDDP F0,%f", /* 0x08 */ - 0,0, "FMULDP F0,%f", /* 0x09 */ - 0,0, "", /* 0x0a */ - R1,0, "FCOMPDP", /* 0x0b */ - 0,0, "FSUBRDP F0,%f", /* 0x0c */ - 0,0, "FSUBDP F0,%f", /* 0x0d */ - 0,0, "FDIVRDP F0,%f", /* 0x0e */ - 0,0, "FDIVDP F0,%f", /* 0x0f */ +[0x00] 0,0, "FADDW %e,F0", +[0x01] 0,0, "FMULW %e,F0", +[0x02] 0,0, "FCOMW %e,F0", +[0x03] 0,0, "FCOMWP %e,F0", +[0x04] 0,0, "FSUBW %e,F0", +[0x05] 0,0, "FSUBRW %e,F0", +[0x06] 0,0, "FDIVW %e,F0", +[0x07] 0,0, "FDIVRW %e,F0", +[0x08] 0,0, "FADDDP F0,%f", +[0x09] 0,0, "FMULDP F0,%f", +[0x0b] R1,0, "FCOMPDP", +[0x0c] 0,0, "FSUBRDP F0,%f", +[0x0d] 0,0, "FSUBDP F0,%f", +[0x0e] 0,0, "FDIVRDP F0,%f", +[0x0f] 0,0, "FDIVDP F0,%f", }; static Optable optabDF[8+8] = { - 0,0, "FMOVW %e,F0", /* 0x00 */ - 0,0, "", /* 0x01 */ - 0,0, "FMOVW F0,%e", /* 0x02 */ - 0,0, "FMOVWP F0,%e", /* 0x03 */ - 0,0, "FBLD %e", /* 0x04 */ - 0,0, "FMOVL %e,F0", /* 0x05 */ - 0,0, "FBSTP %e", /* 0x06 */ - 0,0, "FMOVLP F0,%e", /* 0x07 */ - 0,0, "", /* 0x08 */ - 0,0, "", /* 0x09 */ - 0,0, "", /* 0x0a */ - 0,0, "", /* 0x0b */ - R0,0, "FSTSW %OAX", /* 0x0c */ +[0x00] 0,0, "FMOVW %e,F0", +[0x02] 0,0, "FMOVW F0,%e", +[0x03] 0,0, "FMOVWP F0,%e", +[0x04] 0,0, "FBLD %e", +[0x05] 0,0, "FMOVL %e,F0", +[0x06] 0,0, "FBSTP %e", +[0x07] 0,0, "FMOVLP F0,%e", +[0x0c] R0,0, "FSTSW %OAX", }; static Optable optabF6[8] = { - Ib,0, "TESTB %i,%e", /* 0x00 */ - 0,0, "", /* 0x01 */ - 0,0, "NOTB %e", /* 0x02 */ - 0,0, "NEGB %e", /* 0x03 */ - 0,0, "MULB AL,%e", /* 0x04 */ - 0,0, "IMULB AL,%e", /* 0x05 */ - 0,0, "DIVB AL,%e", /* 0x06 */ - 0,0, "IDIVB AL,%e", /* 0x07 */ +[0x00] Ib,0, "TESTB %i,%e", +[0x02] 0,0, "NOTB %e", +[0x03] 0,0, "NEGB %e", +[0x04] 0,0, "MULB AL,%e", +[0x05] 0,0, "IMULB AL,%e", +[0x06] 0,0, "DIVB AL,%e", +[0x07] 0,0, "IDIVB AL,%e", }; static Optable optabF7[8] = { - Iwd,0, "TEST%S %i,%e", /* 0x00 */ - 0,0, "", /* 0x01 */ - 0,0, "NOT%S %e", /* 0x02 */ - 0,0, "NEG%S %e", /* 0x03 */ - 0,0, "MUL%S %OAX,%e", /* 0x04 */ - 0,0, "IMUL%S %OAX,%e", /* 0x05 */ - 0,0, "DIV%S %OAX,%e", /* 0x06 */ - 0,0, "IDIV%S %OAX,%e", /* 0x07 */ +[0x00] Iwd,0, "TEST%S %i,%e", +[0x02] 0,0, "NOT%S %e", +[0x03] 0,0, "NEG%S %e", +[0x04] 0,0, "MUL%S %OAX,%e", +[0x05] 0,0, "IMUL%S %OAX,%e", +[0x06] 0,0, "DIV%S %OAX,%e", +[0x07] 0,0, "IDIV%S %OAX,%e", }; static Optable optabFE[8] = { - 0,0, "INCB %e", /* 0x00 */ - 0,0, "DECB %e", /* 0x01 */ +[0x00] 0,0, "INCB %e", +[0x01] 0,0, "DECB %e", }; static Optable optabFF[8] = { - 0,0, "INC%S %e", /* 0x00 */ - 0,0, "DEC%S %e", /* 0x01 */ - JUMP,0, "CALL*%S %e", /* 0x02 */ - JUMP,0, "CALLF*%S %e", /* 0x03 */ - JUMP,0, "JMP*%S %e", /* 0x04 */ - JUMP,0, "JMPF*%S %e", /* 0x05 */ - 0,0, "PUSHL %e", /* 0x06 */ +[0x00] 0,0, "INC%S %e", +[0x01] 0,0, "DEC%S %e", +[0x02] JUMP,0, "CALL* %e", +[0x03] JUMP,0, "CALLF* %e", +[0x04] JUMP,0, "JMP* %e", +[0x05] JUMP,0, "JMPF* %e", +[0x06] 0,0, "PUSHL %e", }; -static Optable optable[256] = +static Optable optable[256+1] = { - RMB,0, "ADDB %r,%e", /* 0x00 */ - RM,0, "ADD%S %r,%e", /* 0x01 */ - RMB,0, "ADDB %e,%r", /* 0x02 */ - RM,0, "ADD%S %e,%r", /* 0x03 */ - Ib,0, "ADDB %i,AL", /* 0x04 */ - Iwd,0, "ADD%S %i,%OAX", /* 0x05 */ - 0,0, "PUSHL ES", /* 0x06 */ - 0,0, "POPL ES", /* 0x07 */ - RMB,0, "ORB %r,%e", /* 0x08 */ - RM,0, "OR%S %r,%e", /* 0x09 */ - RMB,0, "ORB %e,%r", /* 0x0a */ - RM,0, "OR%S %e,%r", /* 0x0b */ - Ib,0, "ORB %i,AL", /* 0x0c */ - Iwd,0, "OR%S %i,%OAX", /* 0x0d */ - 0,0, "PUSHL CS", /* 0x0e */ - AUX,0, optab0F, /* 0x0f */ - RMB,0, "ADCB %r,%e", /* 0x10 */ - RM,0, "ADC%S %r,%e", /* 0x11 */ - RMB,0, "ADCB %e,%r", /* 0x12 */ - RM,0, "ADC%S %e,%r", /* 0x13 */ - Ib,0, "ADCB %i,AL", /* 0x14 */ - Iwd,0, "ADC%S %i,%OAX", /* 0x15 */ - 0,0, "PUSHL SS", /* 0x16 */ - 0,0, "POPL SS", /* 0x17 */ - RMB,0, "SBBB %r,%e", /* 0x18 */ - RM,0, "SBB%S %r,%e", /* 0x19 */ - RMB,0, "SBBB %e,%r", /* 0x1a */ - RM,0, "SBB%S %e,%r", /* 0x1b */ - Ib,0, "SBBB %i,AL", /* 0x1c */ - Iwd,0, "SBB%S %i,%OAX", /* 0x1d */ - 0,0, "PUSHL DS", /* 0x1e */ - 0,0, "POPL DS", /* 0x1f */ - RMB,0, "ANDB %r,%e", /* 0x20 */ - RM,0, "AND%S %r,%e", /* 0x21 */ - RMB,0, "ANDB %e,%r", /* 0x22 */ - RM,0, "AND%S %e,%r", /* 0x23 */ - Ib,0, "ANDB %i,AL", /* 0x24 */ - Iwd,0, "AND%S %i,%OAX", /* 0x25 */ - SEG,0, "ES:", /* 0x26 */ - 0,0, "DAA", /* 0x27 */ - RMB,0, "SUBB %r,%e", /* 0x28 */ - RM,0, "SUB%S %r,%e", /* 0x29 */ - RMB,0, "SUBB %e,%r", /* 0x2a */ - RM,0, "SUB%S %e,%r", /* 0x2b */ - Ib,0, "SUBB %i,AL", /* 0x2c */ - Iwd,0, "SUB%S %i,%OAX", /* 0x2d */ - SEG,0, "CS:", /* 0x2e */ - 0,0, "DAS", /* 0x2f */ - RMB,0, "XORB %r,%e", /* 0x30 */ - RM,0, "XOR%S %r,%e", /* 0x31 */ - RMB,0, "XORB %e,%r", /* 0x32 */ - RM,0, "XOR%S %e,%r", /* 0x33 */ - Ib,0, "XORB %i,AL", /* 0x34 */ - Iwd,0, "XOR%S %i,%OAX", /* 0x35 */ - SEG,0, "SS:", /* 0x36 */ - 0,0, "AAA", /* 0x37 */ - RMB,0, "CMPB %r,%e", /* 0x38 */ - RM,0, "CMP%S %r,%e", /* 0x39 */ - RMB,0, "CMPB %e,%r", /* 0x3a */ - RM,0, "CMP%S %e,%r", /* 0x3b */ - Ib,0, "CMPB %i,AL", /* 0x3c */ - Iwd,0, "CMP%S %i,%OAX", /* 0x3d */ - SEG,0, "DS:", /* 0x3e */ - 0,0, "AAS", /* 0x3f */ - 0,0, "INC%S %OAX", /* 0x40 */ - 0,0, "INC%S %OCX", /* 0x41 */ - 0,0, "INC%S %ODX", /* 0x42 */ - 0,0, "INC%S %OBX", /* 0x43 */ - 0,0, "INC%S %OSP", /* 0x44 */ - 0,0, "INC%S %OBP", /* 0x45 */ - 0,0, "INC%S %OSI", /* 0x46 */ - 0,0, "INC%S %ODI", /* 0x47 */ - 0,0, "DEC%S %OAX", /* 0x48 */ - 0,0, "DEC%S %OCX", /* 0x49 */ - 0,0, "DEC%S %ODX", /* 0x4a */ - 0,0, "DEC%S %OBX", /* 0x4b */ - 0,0, "DEC%S %OSP", /* 0x4c */ - 0,0, "DEC%S %OBP", /* 0x4d */ - 0,0, "DEC%S %OSI", /* 0x4e */ - 0,0, "DEC%S %ODI", /* 0x4f */ - 0,0, "PUSH%S %OAX", /* 0x50 */ - 0,0, "PUSH%S %OCX", /* 0x51 */ - 0,0, "PUSH%S %ODX", /* 0x52 */ - 0,0, "PUSH%S %OBX", /* 0x53 */ - 0,0, "PUSH%S %OSP", /* 0x54 */ - 0,0, "PUSH%S %OBP", /* 0x55 */ - 0,0, "PUSH%S %OSI", /* 0x56 */ - 0,0, "PUSH%S %ODI", /* 0x57 */ - 0,0, "POP%S %OAX", /* 0x58 */ - 0,0, "POP%S %OCX", /* 0x59 */ - 0,0, "POP%S %ODX", /* 0x5a */ - 0,0, "POP%S %OBX", /* 0x5b */ - 0,0, "POP%S %OSP", /* 0x5c */ - 0,0, "POP%S %OBP", /* 0x5d */ - 0,0, "POP%S %OSI", /* 0x5e */ - 0,0, "POP%S %ODI", /* 0x5f */ - 0,0, "PUSHA%S", /* 0x60 */ - 0,0, "POPA%S", /* 0x61 */ - RMM,0, "BOUND %e,%r", /* 0x62 */ - RM,0, "ARPL %r,%e", /* 0x63 */ - SEG,0, "FS:", /* 0x64 */ - SEG,0, "GS:", /* 0x65 */ - OPOVER,0, "", /* 0x66 */ - ADDOVER,0, "", /* 0x67 */ - Iwd,0, "PUSH%S %i", /* 0x68 */ - RM,Iwd, "IMUL%S %e,%i,%r", /* 0x69 */ - Ib,0, "PUSH%S %i", /* 0x6a */ - RM,Ibs, "IMUL%S %e,%i,%r", /* 0x6b */ - 0,0, "INSB DX,(%ODI)", /* 0x6c */ - 0,0, "INS%S DX,(%ODI)", /* 0x6d */ - 0,0, "OUTSB (%ASI),DX", /* 0x6e */ - 0,0, "OUTS%S (%ASI),DX", /* 0x6f */ - Jbs,0, "JOS %p", /* 0x70 */ - Jbs,0, "JOC %p", /* 0x71 */ - Jbs,0, "JCS %p", /* 0x72 */ - Jbs,0, "JCC %p", /* 0x73 */ - Jbs,0, "JEQ %p", /* 0x74 */ - Jbs,0, "JNE %p", /* 0x75 */ - Jbs,0, "JLS %p", /* 0x76 */ - Jbs,0, "JHI %p", /* 0x77 */ - Jbs,0, "JMI %p", /* 0x78 */ - Jbs,0, "JPL %p", /* 0x79 */ - Jbs,0, "JPS %p", /* 0x7a */ - Jbs,0, "JPC %p", /* 0x7b */ - Jbs,0, "JLT %p", /* 0x7c */ - Jbs,0, "JGE %p", /* 0x7d */ - Jbs,0, "JLE %p", /* 0x7e */ - Jbs,0, "JGT %p", /* 0x7f */ - RMOPB,0, optab80, /* 0x80 */ - RMOP,0, optab81, /* 0x81 */ - 0,0, "", /* 0x82 */ - RMOP,0, optab83, /* 0x83 */ - RMB,0, "TESTB %r,%e", /* 0x84 */ - RM,0, "TEST%S %r,%e", /* 0x85 */ - RMB,0, "XCHGB %r,%e", /* 0x86 */ - RM,0, "XCHG%S %r,%e", /* 0x87 */ - RMB,0, "MOVB %r,%e", /* 0x88 */ - RM,0, "MOV%S %r,%e", /* 0x89 */ - RMB,0, "MOVB %e,%r", /* 0x8a */ - RM,0, "MOV%S %e,%r", /* 0x8b */ - RM,0, "MOVW %g,%e", /* 0x8c */ - RM,0, "LEA %e,%r", /* 0x8d */ - RM,0, "MOVW %e,%g", /* 0x8e */ - RM,0, "POP%S %e", /* 0x8f */ - 0,0, "NOP", /* 0x90 */ - 0,0, "XCHG %OCX,%OAX", /* 0x91 */ - 0,0, "XCHG %OCX,%OAX", /* 0x92 */ - 0,0, "XCHG %OCX,%OAX", /* 0x93 */ - 0,0, "XCHG %OSP,%OAX", /* 0x94 */ - 0,0, "XCHG %OBP,%OAX", /* 0x95 */ - 0,0, "XCHG %OSI,%OAX", /* 0x96 */ - 0,0, "XCHG %ODI,%OAX", /* 0x97 */ - 0,0, "%X", /* 0x98 */ /* miserable CBW or CWDE */ - 0,0, "%x", /* 0x99 */ /* idiotic CWD or CDQ */ - PTR,0, "CALL%S %d", /* 0x9a */ - 0,0, "WAIT", /* 0x9b */ - 0,0, "PUSHF", /* 0x9c */ - 0,0, "POPF", /* 0x9d */ - 0,0, "SAHF", /* 0x9e */ - 0,0, "LAHF", /* 0x9f */ - Awd,0, "MOVB %i,AL", /* 0xa0 */ - Awd,0, "MOV%S %i,%OAX", /* 0xa1 */ - Awd,0, "MOVB AL,%i", /* 0xa2 */ - Awd,0, "MOV%S %OAX,%i", /* 0xa3 */ - 0,0, "MOVSB (%ASI),(%ADI)", /* 0xa4 */ - 0,0, "MOVS%S (%ASI),(%ADI)", /* 0xa5 */ - 0,0, "CMPSB (%ASI),(%ADI)", /* 0xa6 */ - 0,0, "CMPS%S (%ASI),(%ADI)", /* 0xa7 */ - Ib,0, "TESTB %i,AL", /* 0xa8 */ - Iwd,0, "TEST%S %i,%OAX", /* 0xa9 */ - 0,0, "STOSB AL,(%ADI)", /* 0xaa */ - 0,0, "STOS%S %OAX,(%ADI)", /* 0xab */ - 0,0, "LODSB (%ASI),AL", /* 0xac */ - 0,0, "LODS%S (%ASI),%OAX", /* 0xad */ - 0,0, "SCASB (%ADI),AL", /* 0xae */ - 0,0, "SCAS%S (%ADI),%OAX", /* 0xaf */ - Ib,0, "MOVB %i,AL", /* 0xb0 */ - Ib,0, "MOVB %i,CL", /* 0xb1 */ - Ib,0, "MOVB %i,DL", /* 0xb2 */ - Ib,0, "MOVB %i,BL", /* 0xb3 */ - Ib,0, "MOVB %i,AH", /* 0xb4 */ - Ib,0, "MOVB %i,CH", /* 0xb5 */ - Ib,0, "MOVB %i,DH", /* 0xb6 */ - Ib,0, "MOVB %i,BH", /* 0xb7 */ - Iwd,0, "MOV%S %i,%OAX", /* 0xb8 */ - Iwd,0, "MOV%S %i,%OCX", /* 0xb9 */ - Iwd,0, "MOV%S %i,%ODX", /* 0xba */ - Iwd,0, "MOV%S %i,%OBX", /* 0xbb */ - Iwd,0, "MOV%S %i,%OSP", /* 0xbc */ - Iwd,0, "MOV%S %i,%OBP", /* 0xbd */ - Iwd,0, "MOV%S %i,%OSI", /* 0xbe */ - Iwd,0, "MOV%S %i,%ODI", /* 0xbf */ - RMOPB,0, optabC0, /* 0xc0 */ - RMOP,0, optabC1, /* 0xc1 */ - Iw,0, "RET %i", /* 0xc2 */ - RET,0, "RET", /* 0xc3 */ - RM,0, "LES %e,%r", /* 0xc4 */ - RM,0, "LDS %e,%r", /* 0xc5 */ - RMB,Ib, "MOVB %i,%e", /* 0xc6 */ - RM,Iwd, "MOV%S %i,%e", /* 0xc7 */ - Iw2,Ib, "ENTER %i,%I", /* 0xc8 */ /* loony ENTER */ - RET,0, "LEAVE", /* 0xc9 */ /* bizarre LEAVE */ - Iw,0, "RETF %i", /* 0xca */ - RET,0, "RETF", /* 0xcb */ - 0,0, "INT 3", /* 0xcc */ - Ib,0, "INTB %i", /* 0xcd */ - 0,0, "INTO", /* 0xce */ - 0,0, "IRET", /* 0xcf */ - RMOPB,0, optabD0, /* 0xd0 */ - RMOP,0, optabD1, /* 0xd1 */ - RMOPB,0, optabD2, /* 0xd2 */ - RMOP,0, optabD3, /* 0xd3 */ - OA,0, "AAM", /* 0xd4 */ - OA,0, "AAD", /* 0xd5 */ - 0,0, "", /* 0xd6 */ - 0,0, "XLAT", /* 0xd7 */ - FRMOP,0, optabD8, /* 0xd8 */ - FRMEX,0, optabD9, /* 0xd9 */ - FRMOP,0, optabDA, /* 0xda */ - FRMEX,0, optabDB, /* 0xdb */ - FRMOP,0, optabDC, /* 0xdc */ - FRMOP,0, optabDD, /* 0xdd */ - FRMOP,0, optabDE, /* 0xde */ - FRMOP,0, optabDF, /* 0xdf */ - Jbs,0, "LOOPNE %p", /* 0xe0 */ - Jbs,0, "LOOPE %p", /* 0xe1 */ - Jbs,0, "LOOP %p", /* 0xe2 */ - Jbs,0, "JCXZ %p", /* 0xe3 */ - Ib,0, "INB %i,AL", /* 0xe4 */ - Ib,0, "IN%S %i,%OAX", /* 0xe5 */ - Ib,0, "OUTB AL,%i", /* 0xe6 */ - Ib,0, "OUT%S %OAX,%i", /* 0xe7 */ - Iwds,0, "CALL %p", /* 0xe8 */ - Iwds,0, "JMP %p", /* 0xe9 */ - PTR,0, "JMP %d", /* 0xea */ - Jbs,0, "JMP %p", /* 0xeb */ - 0,0, "INB DX,AL", /* 0xec */ - 0,0, "IN%S DX,%OAX", /* 0xed */ - 0,0, "OUTB AL,DX", /* 0xee */ - 0,0, "OUT%S %OAX,DX", /* 0xef */ - PRE,0, "LOCK", /* 0xf0 */ - 0,0, "", /* 0xf1 */ - PRE,0, "REPNE", /* 0xf2 */ - PRE,0, "REP", /* 0xf3 */ - 0,0, "HALT", /* 0xf4 */ - 0,0, "CMC", /* 0xf5 */ - RMOPB,0, optabF6, /* 0xf6 */ - RMOP,0, optabF7, /* 0xf7 */ - 0,0, "CLC", /* 0xf8 */ - 0,0, "STC", /* 0xf9 */ - 0,0, "CLI", /* 0xfa */ - 0,0, "STI", /* 0xfb */ - 0,0, "CLD", /* 0xfc */ - 0,0, "STD", /* 0xfd */ - RMOPB,0, optabFE, /* 0xfe */ - RMOP,0, optabFF, /* 0xff */ +[0x00] RMB,0, "ADDB %r,%e", +[0x01] RM,0, "ADD%S %r,%e", +[0x02] RMB,0, "ADDB %e,%r", +[0x03] RM,0, "ADD%S %e,%r", +[0x04] Ib,0, "ADDB %i,AL", +[0x05] Iwd,0, "ADD%S %i,%OAX", +[0x06] 0,0, "PUSHL ES", +[0x07] 0,0, "POPL ES", +[0x08] RMB,0, "ORB %r,%e", +[0x09] RM,0, "OR%S %r,%e", +[0x0a] RMB,0, "ORB %e,%r", +[0x0b] RM,0, "OR%S %e,%r", +[0x0c] Ib,0, "ORB %i,AL", +[0x0d] Iwd,0, "OR%S %i,%OAX", +[0x0e] 0,0, "PUSHL CS", +[0x0f] AUXMM,0, optab0F, +[0x10] RMB,0, "ADCB %r,%e", +[0x11] RM,0, "ADC%S %r,%e", +[0x12] RMB,0, "ADCB %e,%r", +[0x13] RM,0, "ADC%S %e,%r", +[0x14] Ib,0, "ADCB %i,AL", +[0x15] Iwd,0, "ADC%S %i,%OAX", +[0x16] 0,0, "PUSHL SS", +[0x17] 0,0, "POPL SS", +[0x18] RMB,0, "SBBB %r,%e", +[0x19] RM,0, "SBB%S %r,%e", +[0x1a] RMB,0, "SBBB %e,%r", +[0x1b] RM,0, "SBB%S %e,%r", +[0x1c] Ib,0, "SBBB %i,AL", +[0x1d] Iwd,0, "SBB%S %i,%OAX", +[0x1e] 0,0, "PUSHL DS", +[0x1f] 0,0, "POPL DS", +[0x20] RMB,0, "ANDB %r,%e", +[0x21] RM,0, "AND%S %r,%e", +[0x22] RMB,0, "ANDB %e,%r", +[0x23] RM,0, "AND%S %e,%r", +[0x24] Ib,0, "ANDB %i,AL", +[0x25] Iwd,0, "AND%S %i,%OAX", +[0x26] SEG,0, "ES:", +[0x27] 0,0, "DAA", +[0x28] RMB,0, "SUBB %r,%e", +[0x29] RM,0, "SUB%S %r,%e", +[0x2a] RMB,0, "SUBB %e,%r", +[0x2b] RM,0, "SUB%S %e,%r", +[0x2c] Ib,0, "SUBB %i,AL", +[0x2d] Iwd,0, "SUB%S %i,%OAX", +[0x2e] SEG,0, "CS:", +[0x2f] 0,0, "DAS", +[0x30] RMB,0, "XORB %r,%e", +[0x31] RM,0, "XOR%S %r,%e", +[0x32] RMB,0, "XORB %e,%r", +[0x33] RM,0, "XOR%S %e,%r", +[0x34] Ib,0, "XORB %i,AL", +[0x35] Iwd,0, "XOR%S %i,%OAX", +[0x36] SEG,0, "SS:", +[0x37] 0,0, "AAA", +[0x38] RMB,0, "CMPB %r,%e", +[0x39] RM,0, "CMP%S %r,%e", +[0x3a] RMB,0, "CMPB %e,%r", +[0x3b] RM,0, "CMP%S %e,%r", +[0x3c] Ib,0, "CMPB %i,AL", +[0x3d] Iwd,0, "CMP%S %i,%OAX", +[0x3e] SEG,0, "DS:", +[0x3f] 0,0, "AAS", +[0x40] 0,0, "INC%S %OAX", +[0x41] 0,0, "INC%S %OCX", +[0x42] 0,0, "INC%S %ODX", +[0x43] 0,0, "INC%S %OBX", +[0x44] 0,0, "INC%S %OSP", +[0x45] 0,0, "INC%S %OBP", +[0x46] 0,0, "INC%S %OSI", +[0x47] 0,0, "INC%S %ODI", +[0x48] 0,0, "DEC%S %OAX", +[0x49] 0,0, "DEC%S %OCX", +[0x4a] 0,0, "DEC%S %ODX", +[0x4b] 0,0, "DEC%S %OBX", +[0x4c] 0,0, "DEC%S %OSP", +[0x4d] 0,0, "DEC%S %OBP", +[0x4e] 0,0, "DEC%S %OSI", +[0x4f] 0,0, "DEC%S %ODI", +[0x50] 0,0, "PUSH%S %OAX", +[0x51] 0,0, "PUSH%S %OCX", +[0x52] 0,0, "PUSH%S %ODX", +[0x53] 0,0, "PUSH%S %OBX", +[0x54] 0,0, "PUSH%S %OSP", +[0x55] 0,0, "PUSH%S %OBP", +[0x56] 0,0, "PUSH%S %OSI", +[0x57] 0,0, "PUSH%S %ODI", +[0x58] 0,0, "POP%S %OAX", +[0x59] 0,0, "POP%S %OCX", +[0x5a] 0,0, "POP%S %ODX", +[0x5b] 0,0, "POP%S %OBX", +[0x5c] 0,0, "POP%S %OSP", +[0x5d] 0,0, "POP%S %OBP", +[0x5e] 0,0, "POP%S %OSI", +[0x5f] 0,0, "POP%S %ODI", +[0x60] 0,0, "PUSHA%S", +[0x61] 0,0, "POPA%S", +[0x62] RMM,0, "BOUND %e,%r", +[0x63] RM,0, "ARPL %r,%e", +[0x64] SEG,0, "FS:", +[0x65] SEG,0, "GS:", +[0x66] OPOVER,0, "", +[0x67] ADDOVER,0, "", +[0x68] Iwd,0, "PUSH%S %i", +[0x69] RM,Iwd, "IMUL%S %e,%i,%r", +[0x6a] Ib,0, "PUSH%S %i", +[0x6b] RM,Ibs, "IMUL%S %e,%i,%r", +[0x6c] 0,0, "INSB DX,(%ODI)", +[0x6d] 0,0, "INS%S DX,(%ODI)", +[0x6e] 0,0, "OUTSB (%ASI),DX", +[0x6f] 0,0, "OUTS%S (%ASI),DX", +[0x70] Jbs,0, "JOS %p", +[0x71] Jbs,0, "JOC %p", +[0x72] Jbs,0, "JCS %p", +[0x73] Jbs,0, "JCC %p", +[0x74] Jbs,0, "JEQ %p", +[0x75] Jbs,0, "JNE %p", +[0x76] Jbs,0, "JLS %p", +[0x77] Jbs,0, "JHI %p", +[0x78] Jbs,0, "JMI %p", +[0x79] Jbs,0, "JPL %p", +[0x7a] Jbs,0, "JPS %p", +[0x7b] Jbs,0, "JPC %p", +[0x7c] Jbs,0, "JLT %p", +[0x7d] Jbs,0, "JGE %p", +[0x7e] Jbs,0, "JLE %p", +[0x7f] Jbs,0, "JGT %p", +[0x80] RMOPB,0, optab80, +[0x81] RMOP,0, optab81, +[0x83] RMOP,0, optab83, +[0x84] RMB,0, "TESTB %r,%e", +[0x85] RM,0, "TEST%S %r,%e", +[0x86] RMB,0, "XCHGB %r,%e", +[0x87] RM,0, "XCHG%S %r,%e", +[0x88] RMB,0, "MOVB %r,%e", +[0x89] RM,0, "MOV%S %r,%e", +[0x8a] RMB,0, "MOVB %e,%r", +[0x8b] RM,0, "MOV%S %e,%r", +[0x8c] RM,0, "MOVW %g,%e", +[0x8d] RM,0, "LEA%S %e,%r", +[0x8e] RM,0, "MOVW %e,%g", +[0x8f] RM,0, "POP%S %e", +[0x90] 0,0, "NOP", +[0x91] 0,0, "XCHG %OCX,%OAX", +[0x92] 0,0, "XCHG %ODX,%OAX", +[0x93] 0,0, "XCHG %OBX,%OAX", +[0x94] 0,0, "XCHG %OSP,%OAX", +[0x95] 0,0, "XCHG %OBP,%OAX", +[0x96] 0,0, "XCHG %OSI,%OAX", +[0x97] 0,0, "XCHG %ODI,%OAX", +[0x98] 0,0, "%W", /* miserable CBW or CWDE */ +[0x99] 0,0, "%w", /* idiotic CWD or CDQ */ +[0x9a] PTR,0, "CALL%S %d", +[0x9b] 0,0, "WAIT", +[0x9c] 0,0, "PUSHF", +[0x9d] 0,0, "POPF", +[0x9e] 0,0, "SAHF", +[0x9f] 0,0, "LAHF", +[0xa0] Awd,0, "MOVB %i,AL", +[0xa1] Awd,0, "MOV%S %i,%OAX", +[0xa2] Awd,0, "MOVB AL,%i", +[0xa3] Awd,0, "MOV%S %OAX,%i", +[0xa4] 0,0, "MOVSB (%ASI),(%ADI)", +[0xa5] 0,0, "MOVS%S (%ASI),(%ADI)", +[0xa6] 0,0, "CMPSB (%ASI),(%ADI)", +[0xa7] 0,0, "CMPS%S (%ASI),(%ADI)", +[0xa8] Ib,0, "TESTB %i,AL", +[0xa9] Iwd,0, "TEST%S %i,%OAX", +[0xaa] 0,0, "STOSB AL,(%ADI)", +[0xab] 0,0, "STOS%S %OAX,(%ADI)", +[0xac] 0,0, "LODSB (%ASI),AL", +[0xad] 0,0, "LODS%S (%ASI),%OAX", +[0xae] 0,0, "SCASB (%ADI),AL", +[0xaf] 0,0, "SCAS%S (%ADI),%OAX", +[0xb0] Ib,0, "MOVB %i,AL", +[0xb1] Ib,0, "MOVB %i,CL", +[0xb2] Ib,0, "MOVB %i,DL", +[0xb3] Ib,0, "MOVB %i,BL", +[0xb4] Ib,0, "MOVB %i,AH", +[0xb5] Ib,0, "MOVB %i,CH", +[0xb6] Ib,0, "MOVB %i,DH", +[0xb7] Ib,0, "MOVB %i,BH", +[0xb8] Iwdq,0, "MOV%S %i,%OAX", +[0xb9] Iwdq,0, "MOV%S %i,%OCX", +[0xba] Iwdq,0, "MOV%S %i,%ODX", +[0xbb] Iwdq,0, "MOV%S %i,%OBX", +[0xbc] Iwdq,0, "MOV%S %i,%OSP", +[0xbd] Iwdq,0, "MOV%S %i,%OBP", +[0xbe] Iwdq,0, "MOV%S %i,%OSI", +[0xbf] Iwdq,0, "MOV%S %i,%ODI", +[0xc0] RMOPB,0, optabC0, +[0xc1] RMOP,0, optabC1, +[0xc2] Iw,0, "RET %i", +[0xc3] RET,0, "RET", +[0xc4] RM,0, "LES %e,%r", +[0xc5] RM,0, "LDS %e,%r", +[0xc6] RMB,Ib, "MOVB %i,%e", +[0xc7] RM,Iwd, "MOV%S %i,%e", +[0xc8] Iw2,Ib, "ENTER %i,%I", /* loony ENTER */ +[0xc9] RET,0, "LEAVE", /* bizarre LEAVE */ +[0xca] Iw,0, "RETF %i", +[0xcb] RET,0, "RETF", +[0xcc] 0,0, "INT 3", +[0xcd] Ib,0, "INTB %i", +[0xce] 0,0, "INTO", +[0xcf] 0,0, "IRET", +[0xd0] RMOPB,0, optabD0, +[0xd1] RMOP,0, optabD1, +[0xd2] RMOPB,0, optabD2, +[0xd3] RMOP,0, optabD3, +[0xd4] OA,0, "AAM", +[0xd5] OA,0, "AAD", +[0xd7] 0,0, "XLAT", +[0xd8] FRMOP,0, optabD8, +[0xd9] FRMEX,0, optabD9, +[0xda] FRMOP,0, optabDA, +[0xdb] FRMEX,0, optabDB, +[0xdc] FRMOP,0, optabDC, +[0xdd] FRMOP,0, optabDD, +[0xde] FRMOP,0, optabDE, +[0xdf] FRMOP,0, optabDF, +[0xe0] Jbs,0, "LOOPNE %p", +[0xe1] Jbs,0, "LOOPE %p", +[0xe2] Jbs,0, "LOOP %p", +[0xe3] Jbs,0, "JCXZ %p", +[0xe4] Ib,0, "INB %i,AL", +[0xe5] Ib,0, "IN%S %i,%OAX", +[0xe6] Ib,0, "OUTB AL,%i", +[0xe7] Ib,0, "OUT%S %OAX,%i", +[0xe8] Iwds,0, "CALL %p", +[0xe9] Iwds,0, "JMP %p", +[0xea] PTR,0, "JMP %d", +[0xeb] Jbs,0, "JMP %p", +[0xec] 0,0, "INB DX,AL", +[0xed] 0,0, "IN%S DX,%OAX", +[0xee] 0,0, "OUTB AL,DX", +[0xef] 0,0, "OUT%S %OAX,DX", +[0xf0] PRE,0, "LOCK", +[0xf2] OPRE,0, "REPNE", +[0xf3] OPRE,0, "REP", +[0xf4] 0,0, "HLT", +[0xf5] 0,0, "CMC", +[0xf6] RMOPB,0, optabF6, +[0xf7] RMOP,0, optabF7, +[0xf8] 0,0, "CLC", +[0xf9] 0,0, "STC", +[0xfa] 0,0, "CLI", +[0xfb] 0,0, "STI", +[0xfc] 0,0, "CLD", +[0xfd] 0,0, "STD", +[0xfe] RMOPB,0, optabFE, +[0xff] RMOP,0, optabFF, +[0x100] RM,0, "MOVLQSX %r,%e", }; /* * get a byte of the instruction */ static int -igetc(Map * map, Instr *ip, uchar *c) +igetc(Map *map, Instr *ip, uchar *c) { if(ip->n+1 > sizeof(ip->mem)){ werrstr("instruction too long"); @@ -1163,7 +1248,7 @@ igetc(Map * map, Instr *ip, uchar *c) static int igets(Map *map, Instr *ip, ushort *sp) { - uchar c; + uchar c; ushort s; if (igetc(map, ip, &c) < 0) @@ -1195,8 +1280,27 @@ igetl(Map *map, Instr *ip, ulong *lp) return 1; } +/* + * get 8 bytes of the instruction + */ static int -getdisp(Map *map, Instr *ip, int mod, int rm, int code) +igetq(Map *map, Instr *ip, vlong *qp) +{ + ulong l; + uvlong q; + + if (igetl(map, ip, &l) < 0) + return -1; + q = l; + if (igetl(map, ip, &l) < 0) + return -1; + q |= ((uvlong)l<<32); + *qp = q; + return 1; +} + +static int +getdisp(Map *map, Instr *ip, int mod, int rm, int code, int pcrel) { uchar c; ushort s; @@ -1214,6 +1318,8 @@ getdisp(Map *map, Instr *ip, int mod, int rm, int code) if (ip->asize == 'E') { if (igetl(map, ip, &ip->disp) < 0) return -1; + if (mod == 0) + ip->rip = pcrel; } else { if (igets(map, ip, &s) < 0) return -1; @@ -1238,11 +1344,11 @@ modrm(Map *map, Instr *ip, uchar c) ip->mod = mod; ip->base = rm; ip->reg = (c>>3)&7; + ip->rip = 0; if (mod == 3) /* register */ return 1; if (ip->asize == 0) { /* 16-bit mode */ - switch(rm) - { + switch(rm) { case 0: ip->base = BX; ip->index = SI; break; @@ -1270,7 +1376,7 @@ modrm(Map *map, Instr *ip, uchar c) default: break; } - return getdisp(map, ip, mod, rm, 6); + return getdisp(map, ip, mod, rm, 6, 0); } if (rm == 4) { /* scummy sib byte */ if (igetc(map, ip, &c) < 0) @@ -1280,21 +1386,22 @@ modrm(Map *map, Instr *ip, uchar c) if (ip->index == 4) ip->index = -1; ip->base = c&0x07; - return getdisp(map, ip, mod, ip->base, 5); + return getdisp(map, ip, mod, ip->base, 5, 0); } - return getdisp(map, ip, mod, rm, 5); + return getdisp(map, ip, mod, rm, 5, ip->amd64); } static Optable * -mkinstr(Map *map, Instr *ip, ulong pc) +mkinstr(Map *map, Instr *ip, uvlong pc) { - int i, n; + int i, n, norex; uchar c; ushort s; Optable *op, *obase; char buf[128]; memset(ip, 0, sizeof(*ip)); + norex = 1; ip->base = -1; ip->index = -1; if(asstype == AI8086) @@ -1302,13 +1409,27 @@ mkinstr(Map *map, Instr *ip, ulong pc) else { ip->osize = 'L'; ip->asize = 'E'; + ip->amd64 = asstype != AI386; + norex = 0; } ip->addr = pc; if (igetc(map, ip, &c) < 0) return 0; obase = optable; newop: + if(ip->amd64 && !norex){ + if(c >= 0x40 && c <= 0x4f) { + ip->rex = c; + if(igetc(map, ip, &c) < 0) + return 0; + } + if(c == 0x63){ + op = &obase[0x100]; /* MOVLQSX */ + goto hack; + } + } op = &obase[c]; +hack: if (op->proto == 0) { badop: n = snprint(buf, sizeof(buf), "opcode: ??"); @@ -1319,12 +1440,12 @@ badop: return 0; } for(i = 0; i < 2 && op->operand[i]; i++) { - switch(op->operand[i]) - { + switch(op->operand[i]) { case Ib: /* 8-bit immediate - (no sign extension)*/ if (igetc(map, ip, &c) < 0) return 0; ip->imm = c&0xff; + ip->imm64 = ip->imm; break; case Jbs: /* 8-bit jump immediate (sign extended) */ if (igetc(map, ip, &c) < 0) @@ -1333,6 +1454,7 @@ badop: ip->imm = c|0xffffff00; else ip->imm = c&0xff; + ip->imm64 = (long)ip->imm; ip->jumptype = Jbs; break; case Ibs: /* 8-bit immediate (sign extended) */ @@ -1345,11 +1467,13 @@ badop: ip->imm = c|0xff00; else ip->imm = c&0xff; + ip->imm64 = (long)ip->imm; break; case Iw: /* 16-bit immediate -> imm */ if (igets(map, ip, &s) < 0) return 0; ip->imm = s&0xffff; + ip->imm64 = ip->imm; ip->jumptype = Iw; break; case Iw2: /* 16-bit immediate -> in imm2*/ @@ -1357,10 +1481,31 @@ badop: return 0; ip->imm2 = s&0xffff; break; - case Iwd: /* Operand-sized immediate (no sign extension)*/ + case Iwd: /* Operand-sized immediate (no sign extension unless 64 bits)*/ if (ip->osize == 'L') { if (igetl(map, ip, &ip->imm) < 0) return 0; + ip->imm64 = ip->imm; + if(ip->rex&REXW && (ip->imm & (1<<31)) != 0) + ip->imm64 |= (vlong)~0 << 32; + } else { + if (igets(map, ip, &s)< 0) + return 0; + ip->imm = s&0xffff; + ip->imm64 = ip->imm; + } + break; + case Iwdq: /* Operand-sized immediate, possibly big */ + if (ip->osize == 'L') { + if (igetl(map, ip, &ip->imm) < 0) + return 0; + ip->imm64 = ip->imm; + if (ip->rex & REXW) { + ulong l; + if (igetl(map, ip, &l) < 0) + return 0; + ip->imm64 |= (uvlong)l << 32; + } } else { if (igets(map, ip, &s)< 0) return 0; @@ -1371,6 +1516,7 @@ badop: if (ip->asize == 'E') { if (igetl(map, ip, &ip->imm) < 0) return 0; + /* TO DO: REX */ } else { if (igets(map, ip, &s)< 0) return 0; @@ -1432,8 +1578,10 @@ badop: return 0; if (modrm(map, ip, c) < 0) return 0; - c = ip->reg; obase = (Optable*)op->proto; + if(ip->amd64 && obase == optab0F01 && c == 0xF8) + return optab0F01F8; + c = ip->reg; goto newop; case FRMOP: /* FP R/M field with op code (/digit) */ if (igetc(map, ip, &c) < 0) @@ -1490,15 +1638,35 @@ badop: return 0; ip->jumptype = PTR; break; + case AUXMM: /* Multi-byte op code; prefix determines table selection */ + if (igetc(map, ip, &c) < 0) + return 0; + obase = (Optable*)op->proto; + switch (ip->opre) { + case 0x66: op = optab660F; break; + case 0xF2: op = optabF20F; break; + case 0xF3: op = optabF30F; break; + default: op = nil; break; + } + if(op != nil && op[c].proto != nil) + obase = op; + norex = 1; /* no more rex prefixes */ + /* otherwise the optab entry captures it */ + goto newop; case AUX: /* Multi-byte op code - Auxiliary table */ obase = (Optable*)op->proto; if (igetc(map, ip, &c) < 0) return 0; goto newop; + case OPRE: /* Instr Prefix or media op */ + ip->opre = c; + /* fall through */ case PRE: /* Instr Prefix */ ip->prefix = (char*)op->proto; if (igetc(map, ip, &c) < 0) return 0; + if (ip->opre && c == 0x0F) + ip->prefix = 0; goto newop; case SEG: /* Segment Prefix */ ip->segment = (char*)op->proto; @@ -1506,9 +1674,14 @@ badop: return 0; goto newop; case OPOVER: /* Operand size override */ + ip->opre = c; ip->osize = 'W'; if (igetc(map, ip, &c) < 0) return 0; + if (c == 0x0F) + ip->osize = 'L'; + else if (ip->amd64 && (c&0xF0) == 0x40) + ip->osize = 'Q'; goto newop; case ADDOVER: /* Address size override */ ip->asize = 0; @@ -1527,6 +1700,8 @@ badop: return op; } +#pragma varargck argpos bprint 2 + static void bprint(Instr *ip, char *fmt, ...) { @@ -1548,23 +1723,36 @@ bprint(Instr *ip, char *fmt, ...) #define ONAME(ip) "" static char *reg[] = { - "AX", /* 0 */ - "CX", /* 1 */ - "DX", /* 2 */ - "BX", /* 3 */ - "SP", /* 4 */ - "BP", /* 5 */ - "SI", /* 6 */ - "DI", /* 7 */ +[AX] "AX", +[CX] "CX", +[DX] "DX", +[BX] "BX", +[SP] "SP", +[BP] "BP", +[SI] "SI", +[DI] "DI", + + /* amd64 */ +[R8] "R8", +[R9] "R9", +[R10] "R10", +[R11] "R11", +[R12] "R12", +[R13] "R13", +[R14] "R14", +[R15] "R15", }; static char *breg[] = { "AL", "CL", "DL", "BL", "AH", "CH", "DH", "BH" }; +static char *breg64[] = { "AL", "CL", "DL", "BL", "SPB", "BPB", "SIB", "DIB", + "R8B", "R9B", "R10B", "R11B", "R12B", "R13B", "R14B", "R15B" }; static char *sreg[] = { "ES", "CS", "SS", "DS", "FS", "GS" }; static void plocal(Instr *ip) { - int ret, offset; + int ret; + long offset; Symbol s; char *reg; @@ -1589,60 +1777,143 @@ plocal(Instr *ip) bprint(ip, "%lux%s", offset, reg); } -static void -pea(Instr *ip) +static int +isjmp(Instr *ip) { - if (ip->mod == 3) { - if (ip->osize == 'B') - bprint(ip, breg[ip->base]); - else - bprint(ip, "%s%s", ANAME(ip), reg[ip->base]); - return; + switch(ip->jumptype){ + case Iwds: + case Jbs: + case JUMP: + return 1; + default: + return 0; } - if (ip->segment) - bprint(ip, ip->segment); - if (ip->asize == 'E' && ip->base == SP) - plocal(ip); - else { - bprint(ip,"%lux", ip->disp); - if (ip->base >= 0) - bprint(ip,"(%s%s)", ANAME(ip), reg[ip->base]); +} + +/* + * This is too smart for its own good, but it really is nice + * to have accurate translations when debugging, and it + * helps us identify which code is different in binaries that + * are changed on sources. + */ +static int +issymref(Instr *ip, Symbol *s, long w, long val) +{ + Symbol next, tmp; + long isstring, size; + + if (isjmp(ip)) + return 1; + if (s->class==CTEXT && w==0) + return 1; + if (s->class==CDATA) { + /* use first bss symbol (or "end") rather than edata */ + if (s->name[0]=='e' && strcmp(s->name, "edata") == 0){ + if((s ->index >= 0 && globalsym(&tmp, s->index+1) && tmp.value==s->value) + || (s->index > 0 && globalsym(&tmp, s->index-1) && tmp.value==s->value)) + *s = tmp; + } + if (w == 0) + return 1; + for (next=*s; next.value==s->value; next=tmp) + if (!globalsym(&tmp, next.index+1)) + break; + size = next.value - s->value; + if (w >= size) + return 0; + if (w > size-w) + w = size-w; + /* huge distances are usually wrong except in .string */ + isstring = (s->name[0]=='.' && strcmp(s->name, ".string") == 0); + if (w > 8192 && !isstring) + return 0; + /* medium distances are tricky - look for constants */ + /* near powers of two */ + if ((val&(val-1)) == 0 || (val&(val+1)) == 0) + return 0; + return 1; } - if (ip->index >= 0) - bprint(ip,"(%s%s*%d)", ANAME(ip), reg[ip->index], 1<<ip->ss); + return 0; } static void -immediate(Instr *ip, long val) +immediate(Instr *ip, vlong val) { Symbol s; long w; - if (findsym(val, CANY, &s)) { + if (findsym(val, CANY, &s)) { /* TO DO */ w = val - s.value; if (w < 0) w = -w; - if (w < 4096) { + if (issymref(ip, &s, w, val)) { if (w) bprint(ip, "%s+%lux(SB)", s.name, w); else bprint(ip, "%s(SB)", s.name); return; } +/* + if (s.class==CDATA && globalsym(&s, s.index+1)) { + w = s.value - val; + if (w < 0) + w = -w; + if (w < 4096) { + bprint(ip, "%s-%lux(SB)", s.name, w); + return; + } + } +*/ + } + if((ip->rex & REXW) == 0) + bprint(ip, "%lux", (long)val); + else + bprint(ip, "%llux", val); +} + +static void +pea(Instr *ip) +{ + if (ip->mod == 3) { + if (ip->osize == 'B') + bprint(ip, (ip->rex & REXB? breg64: breg)[ip->base]); + else if(ip->rex & REXB) + bprint(ip, "%s%s", ANAME(ip), reg[ip->base+8]); + else + bprint(ip, "%s%s", ANAME(ip), reg[ip->base]); + return; + } + if (ip->segment) + bprint(ip, ip->segment); + if (ip->asize == 'E' && ip->base == SP) + plocal(ip); + else { + if (ip->base < 0) + immediate(ip, ip->disp); + else { + bprint(ip, "%lux", ip->disp); + if(ip->rip) + bprint(ip, "(RIP)"); + bprint(ip,"(%s%s)", ANAME(ip), reg[ip->rex&REXB? ip->base+8: ip->base]); + } } - bprint(ip, "%lux", val); + if (ip->index >= 0) + bprint(ip,"(%s%s*%d)", ANAME(ip), reg[ip->rex&REXX? ip->index+8: ip->index], 1<<ip->ss); } static void prinstr(Instr *ip, char *fmt) { + vlong v; + if (ip->prefix) bprint(ip, "%s ", ip->prefix); for (; *fmt && ip->curr < ip->end; fmt++) { - if (*fmt != '%') + if (*fmt != '%'){ *ip->curr++ = *fmt; - else switch(*++fmt) - { + continue; + } + switch(*++fmt){ case '%': *ip->curr++ = '%'; break; @@ -1667,13 +1938,29 @@ prinstr(Instr *ip, char *fmt) break; case 'i': bprint(ip, "$"); - immediate(ip,ip->imm); + v = ip->imm; + if(ip->rex & REXW) + v = ip->imm64; + immediate(ip, v); break; case 'R': - bprint(ip, "%s%s", ONAME(ip), reg[ip->reg]); + bprint(ip, "%s%s", ONAME(ip), reg[ip->rex&REXR? ip->reg+8: ip->reg]); break; case 'S': - bprint(ip, "%c", ip->osize); + if(ip->osize == 'Q' || ip->osize == 'L' && ip->rex & REXW) + bprint(ip, "Q"); + else + bprint(ip, "%c", ip->osize); + break; + case 's': + if(ip->opre == 0 || ip->opre == 0x66) + bprint(ip, "P"); + else + bprint(ip, "S"); + if(ip->opre == 0xf2 || ip->opre == 0x66) + bprint(ip, "D"); + else + bprint(ip, "S"); break; case 'T': if (ip->reg == 6 || ip->reg == 7) @@ -1681,14 +1968,30 @@ prinstr(Instr *ip, char *fmt) else bprint(ip, "???"); break; - case 'X': - if (ip->osize == 'L') + case 'W': + if (ip->osize == 'Q' || ip->osize == 'L' && ip->rex & REXW) + bprint(ip, "CDQE"); + else if (ip->osize == 'L') bprint(ip,"CWDE"); else bprint(ip, "CBW"); break; case 'd': - bprint(ip,"%lux:%lux",ip->seg,ip->disp); + bprint(ip,"%ux:%lux",ip->seg,ip->disp); + break; + case 'm': + if (ip->mod == 3 && ip->osize != 'B') { + if(fmt[1] != '*'){ + if(ip->opre != 0) { + bprint(ip, "X%d", ip->rex&REXB? ip->base+8: ip->base); + break; + } + } else + fmt++; + bprint(ip, "M%d", ip->base); + break; + } + pea(ip); break; case 'e': pea(ip); @@ -1703,20 +2006,42 @@ prinstr(Instr *ip, char *fmt) bprint(ip,"???"); break; case 'p': - immediate(ip, ip->imm+ip->addr+ip->n); + /* + * signed immediate in the ulong ip->imm. + */ + v = (long)ip->imm; + immediate(ip, v+ip->addr+ip->n); break; case 'r': if (ip->osize == 'B') - bprint(ip,"%s",breg[ip->reg]); + bprint(ip,"%s", (ip->rex? breg64: breg)[ip->rex&REXR? ip->reg+8: ip->reg]); else - bprint(ip, reg[ip->reg]); + bprint(ip, reg[ip->rex&REXR? ip->reg+8: ip->reg]); break; - case 'x': - if (ip->osize == 'L') + case 'w': + if (ip->osize == 'Q' || ip->rex & REXW) + bprint(ip, "CQO"); + else if (ip->osize == 'L') bprint(ip,"CDQ"); else bprint(ip, "CWD"); break; + case 'M': + if(ip->opre != 0) + bprint(ip, "X%d", ip->rex&REXR? ip->reg+8: ip->reg); + else + bprint(ip, "M%d", ip->reg); + break; + case 'x': + if (ip->mod == 3 && ip->osize != 'B') { + bprint(ip, "X%d", ip->rex&REXB? ip->base+8: ip->base); + break; + } + pea(ip); + break; + case 'X': + bprint(ip, "X%d", ip->rex&REXR? ip->reg+8: ip->reg); + break; default: bprint(ip, "%%%c", *fmt); break; @@ -1726,15 +2051,14 @@ prinstr(Instr *ip, char *fmt) } static int -i386inst(Map *map, ulong pc, char modifier, char *buf, int n) +i386inst(Map *map, uvlong pc, char modifier, char *buf, int n) { - Instr instr; + Instr instr; Optable *op; USED(modifier); op = mkinstr(map, &instr, pc); if (op == 0) { - buf[0] = 0; errstr(buf, n); return -1; } @@ -1745,13 +2069,12 @@ i386inst(Map *map, ulong pc, char modifier, char *buf, int n) } static int -i386das(Map *map, ulong pc, char *buf, int n) +i386das(Map *map, uvlong pc, char *buf, int n) { - Instr instr; + Instr instr; int i; if (mkinstr(map, &instr, pc) == 0) { - buf[0] = 0; errstr(buf, n); return -1; } @@ -1765,7 +2088,7 @@ i386das(Map *map, ulong pc, char *buf, int n) } static int -i386instlen(Map *map, ulong pc) +i386instlen(Map *map, uvlong pc) { Instr i; @@ -1775,12 +2098,13 @@ i386instlen(Map *map, ulong pc) } static int -i386foll(Map *map, ulong pc, Rgetter rget, ulong *foll) +i386foll(Map *map, uvlong pc, Rgetter rget, uvlong *foll) { Instr i; Optable *op; ushort s; - ulong l, addr; + uvlong l, addr; + vlong v; int n; op = mkinstr(map, &i, pc); @@ -1793,15 +2117,16 @@ i386foll(Map *map, ulong pc, Rgetter rget, ulong *foll) case RET: /* RETURN or LEAVE */ case Iw: /* RETURN */ if (strcmp(op->proto, "LEAVE") == 0) { - if (get4(map, (*rget)(map, "BP"), (long*)&l) < 0) + if (geta(map, (*rget)(map, "BP"), &l) < 0) return -1; - } else if (get4(map, (*rget)(map, mach->sp), (long*)&l) < 0) + } else if (geta(map, (*rget)(map, mach->sp), &l) < 0) return -1; foll[0] = l; return 1; case Iwds: /* pc relative JUMP or CALL*/ case Jbs: /* pc relative JUMP or CALL */ - foll[0] = pc+i.imm+i.n; + v = (long)i.imm; + foll[0] = pc+v+i.n; n = 1; break; case PTR: /* seg:displacement JUMP or CALL */ @@ -1810,28 +2135,28 @@ i386foll(Map *map, ulong pc, Rgetter rget, ulong *foll) case JUMP: /* JUMP or CALL EA */ if(i.mod == 3) { - foll[0] = (*rget)(map, reg[i.base]); + foll[0] = (*rget)(map, reg[i.rex&REXB? i.base+8: i.base]); return 1; } /* calculate the effective address */ addr = i.disp; if (i.base >= 0) { - if (get4(map, (*rget)(map, reg[i.base]), (long*)&l) < 0) + if (geta(map, (*rget)(map, reg[i.rex&REXB? i.base+8: i.base]), &l) < 0) return -1; addr += l; } if (i.index >= 0) { - if (get4(map, (*rget)(map, reg[i.index]), (long*)&l) < 0) + if (geta(map, (*rget)(map, reg[i.rex&REXX? i.index+8: i.index]), &l) < 0) return -1; addr += l*(1<<i.ss); } /* now retrieve a seg:disp value at that address */ - if (get2(map, addr, &s) < 0) /* seg */ + if (get2(map, addr, &s) < 0) /* seg */ return -1; foll[0] = s<<4; addr += 2; if (i.asize == 'L') { - if (get4(map, addr, (long*)&l) < 0) /* disp32 */ + if (geta(map, addr, &l) < 0) /* disp32 */ return -1; foll[0] += l; } else { /* disp16 */ diff --git a/utils/libmach/9.c b/utils/libmach/9.c new file mode 100644 index 00000000..aeeebae3 --- /dev/null +++ b/utils/libmach/9.c @@ -0,0 +1,120 @@ +/* + * PowerPC 64 definition + * forsyth@vitanuova.com + */ +#include <lib9.h> +#include <bio.h> +#include "ureg9.h" +#include <mach.h> + + +#define REGOFF(x) offsetof(struct Ureg, x) + +#define R31 REGOFF(r31) +#define FP_REG(x) (R31+4+8*(x)) + +#define REGSIZE sizeof(struct Ureg) +#define FPREGSIZE (8*33) + +Reglist power64reglist[] = { + {"CAUSE", REGOFF(cause), RINT|RRDONLY, 'Y'}, + {"TRAP", REGOFF(cause), RINT|RRDONLY, 'Y'}, /* alias for acid */ + {"MSR", REGOFF(msr), RINT|RRDONLY, 'Y'}, + {"PC", REGOFF(pc), RINT, 'Y'}, + {"LR", REGOFF(lr), RINT, 'Y'}, + {"CR", REGOFF(cr), RINT, 'X'}, + {"XER", REGOFF(xer), RINT, 'Y'}, + {"CTR", REGOFF(ctr), RINT, 'Y'}, + {"PC", REGOFF(pc), RINT, 'Y'}, + {"SP", REGOFF(sp), RINT, 'Y'}, + {"R0", REGOFF(r0), RINT, 'Y'}, + /* R1 is SP */ + {"R2", REGOFF(r2), RINT, 'Y'}, + {"R3", REGOFF(r3), RINT, 'Y'}, + {"R4", REGOFF(r4), RINT, 'Y'}, + {"R5", REGOFF(r5), RINT, 'Y'}, + {"R6", REGOFF(r6), RINT, 'Y'}, + {"R7", REGOFF(r7), RINT, 'Y'}, + {"R8", REGOFF(r8), RINT, 'Y'}, + {"R9", REGOFF(r9), RINT, 'Y'}, + {"R10", REGOFF(r10), RINT, 'Y'}, + {"R11", REGOFF(r11), RINT, 'Y'}, + {"R12", REGOFF(r12), RINT, 'Y'}, + {"R13", REGOFF(r13), RINT, 'Y'}, + {"R14", REGOFF(r14), RINT, 'Y'}, + {"R15", REGOFF(r15), RINT, 'Y'}, + {"R16", REGOFF(r16), RINT, 'Y'}, + {"R17", REGOFF(r17), RINT, 'Y'}, + {"R18", REGOFF(r18), RINT, 'Y'}, + {"R19", REGOFF(r19), RINT, 'Y'}, + {"R20", REGOFF(r20), RINT, 'Y'}, + {"R21", REGOFF(r21), RINT, 'Y'}, + {"R22", REGOFF(r22), RINT, 'Y'}, + {"R23", REGOFF(r23), RINT, 'Y'}, + {"R24", REGOFF(r24), RINT, 'Y'}, + {"R25", REGOFF(r25), RINT, 'Y'}, + {"R26", REGOFF(r26), RINT, 'Y'}, + {"R27", REGOFF(r27), RINT, 'Y'}, + {"R28", REGOFF(r28), RINT, 'Y'}, + {"R29", REGOFF(r29), RINT, 'Y'}, + {"R30", REGOFF(r30), RINT, 'Y'}, + {"R31", REGOFF(r31), RINT, 'Y'}, + {"F0", FP_REG(0), RFLT, 'F'}, + {"F1", FP_REG(1), RFLT, 'F'}, + {"F2", FP_REG(2), RFLT, 'F'}, + {"F3", FP_REG(3), RFLT, 'F'}, + {"F4", FP_REG(4), RFLT, 'F'}, + {"F5", FP_REG(5), RFLT, 'F'}, + {"F6", FP_REG(6), RFLT, 'F'}, + {"F7", FP_REG(7), RFLT, 'F'}, + {"F8", FP_REG(8), RFLT, 'F'}, + {"F9", FP_REG(9), RFLT, 'F'}, + {"F10", FP_REG(10), RFLT, 'F'}, + {"F11", FP_REG(11), RFLT, 'F'}, + {"F12", FP_REG(12), RFLT, 'F'}, + {"F13", FP_REG(13), RFLT, 'F'}, + {"F14", FP_REG(14), RFLT, 'F'}, + {"F15", FP_REG(15), RFLT, 'F'}, + {"F16", FP_REG(16), RFLT, 'F'}, + {"F17", FP_REG(17), RFLT, 'F'}, + {"F18", FP_REG(18), RFLT, 'F'}, + {"F19", FP_REG(19), RFLT, 'F'}, + {"F20", FP_REG(20), RFLT, 'F'}, + {"F21", FP_REG(21), RFLT, 'F'}, + {"F22", FP_REG(22), RFLT, 'F'}, + {"F23", FP_REG(23), RFLT, 'F'}, + {"F24", FP_REG(24), RFLT, 'F'}, + {"F25", FP_REG(25), RFLT, 'F'}, + {"F26", FP_REG(26), RFLT, 'F'}, + {"F27", FP_REG(27), RFLT, 'F'}, + {"F28", FP_REG(28), RFLT, 'F'}, + {"F29", FP_REG(29), RFLT, 'F'}, + {"F30", FP_REG(30), RFLT, 'F'}, + {"F31", FP_REG(31), RFLT, 'F'}, + {"FPSCR", FP_REG(32)+4, RFLT, 'X'}, + { 0 } +}; + + /* the machine description */ +Mach mpower64 = +{ + "power64", + MPOWER64, /* machine type */ + power64reglist, /* register set */ + REGSIZE, /* number of bytes in register set */ + FPREGSIZE, /* number of bytes in FP register set */ + "PC", /* name of PC */ + "SP", /* name of SP */ + "LR", /* name of link register */ + "setSB", /* static base register name */ + 0, /* value */ + 0x1000, /* page size */ + 0x80000000ULL, /* kernel base */ + 0, /* kernel text mask */ + 0x7FFFFFFFULL, /* user stack top */ + 4, /* quantization of pc */ + 8, /* szaddr */ + 8, /* szreg */ + 4, /* szfloat */ + 8, /* szdouble */ +}; diff --git a/utils/libmach/9obj.c b/utils/libmach/9obj.c new file mode 100644 index 00000000..4ec76b98 --- /dev/null +++ b/utils/libmach/9obj.c @@ -0,0 +1,155 @@ +/* + * 9obj.c - identify and parse a PowerPC-64 object file + * forsyth@terzarima.net + */ +#include <lib9.h> +#include <bio.h> +#include "mach.h" +#include "9c/9.out.h" +#include "obj.h" + +typedef struct Addr Addr; +struct Addr +{ + char type; + char sym; + char name; +}; +static Addr addr(Biobuf*); +static char type2char(int); +static void skip(Biobuf*, int); + +int +_is9(char *s) +{ + return (s[0]&0377) == ANAME /* ANAME */ + && (s[1]&0377) == ANAME>>8 + && s[2] == D_FILE /* type */ + && s[3] == 1 /* sym */ + && s[4] == '<'; /* name of file */ +} + +int +_read9(Biobuf *bp, Prog *p) +{ + int as, n, c; + Addr a; + + as = Bgetc(bp); /* as(low) */ + if(as < 0) + return 0; + c = Bgetc(bp); /* as(high) */ + if(c < 0) + return 0; + as |= ((c & 0xff) << 8); + p->kind = aNone; + p->sig = 0; + if(as == ANAME || as == ASIGNAME){ + if(as == ASIGNAME){ + Bread(bp, &p->sig, 4); + p->sig = beswal(p->sig); + } + p->kind = aName; + p->type = type2char(Bgetc(bp)); /* type */ + p->sym = Bgetc(bp); /* sym */ + n = 0; + for(;;) { + as = Bgetc(bp); + if(as < 0) + return 0; + n++; + if(as == 0) + break; + } + p->id = malloc(n); + if(p->id == 0) + return 0; + Bseek(bp, -n, 1); + if(Bread(bp, p->id, n) != n) + return 0; + return 1; + } + if(as == ATEXT) + p->kind = aText; + else if(as == AGLOBL) + p->kind = aData; + n = Bgetc(bp); /* reg and flag */ + skip(bp, 4); /* lineno(4) */ + a = addr(bp); + if(n & 0x40) + addr(bp); + addr(bp); + if(a.type != D_OREG || a.name != D_STATIC && a.name != D_EXTERN) + p->kind = aNone; + p->sym = a.sym; + return 1; +} + +static Addr +addr(Biobuf *bp) +{ + Addr a; + vlong off; + long l; + + a.type = Bgetc(bp); /* a.type */ + skip(bp,1); /* reg */ + a.sym = Bgetc(bp); /* sym index */ + a.name = Bgetc(bp); /* sym type */ + switch(a.type){ + default: + case D_NONE: case D_REG: case D_FREG: case D_CREG: + case D_FPSCR: case D_MSR: + break; + case D_SPR: + case D_OREG: + case D_CONST: + case D_BRANCH: + case D_DCONST: + case D_DCR: + l = Bgetc(bp); + l |= Bgetc(bp) << 8; + l |= Bgetc(bp) << 16; + l |= Bgetc(bp) << 24; + off = l; + if(a.type == D_DCONST){ + l = Bgetc(bp); + l |= Bgetc(bp) << 8; + l |= Bgetc(bp) << 16; + l |= Bgetc(bp) << 24; + off = ((vlong)l << 32) | (off & 0xFFFFFFFF); + a.type = D_CONST; /* perhaps */ + } + if(off < 0) + off = -off; + if(a.sym && (a.name==D_PARAM || a.name==D_AUTO)) + _offset(a.sym, off); + break; + case D_SCONST: + skip(bp, NSNAME); + break; + case D_FCONST: + skip(bp, 8); + break; + } + return a; +} + +static char +type2char(int t) +{ + switch(t){ + case D_EXTERN: return 'U'; + case D_STATIC: return 'b'; + case D_AUTO: return 'a'; + case D_PARAM: return 'p'; + default: return UNKNOWN; + } +} + +static void +skip(Biobuf *bp, int n) +{ + while (n-- > 0) + Bgetc(bp); +} diff --git a/utils/libmach/a.out.h b/utils/libmach/a.out.h index 8c0b7137..59077860 100644 --- a/utils/libmach/a.out.h +++ b/utils/libmach/a.out.h @@ -11,7 +11,6 @@ struct Exec long pcsz; /* size of pc/line number table */ }; - #define HDR_MAGIC 0x00008000 /* header expansion */ #define _MAGIC(f, b) ((f)|((((4*(b))+0)*(b))+7)) @@ -30,16 +29,18 @@ struct Exec #define P_MAGIC _MAGIC(0, 24) /* mips 3000 LE */ #define U_MAGIC _MAGIC(0, 25) /* sparc64 */ #define S_MAGIC _MAGIC(HDR_MAGIC, 26) /* amd64 */ +#define T_MAGIC _MAGIC(HDR_MAGIC, 27) /* powerpc64 */ #define MIN_MAGIC 8 -#define MAX_MAGIC 26 /* <= 90 */ +#define MAX_MAGIC 27 /* <= 90 */ -#define DYN_MAGIC 0x80000000 /* or'd in for dynamically loaded modules */ +#define DYN_MAGIC 0x80000000 /* dlm */ typedef struct Sym Sym; struct Sym { - long value; + vlong value; + uint sig; char type; char *name; }; diff --git a/utils/libmach/access.c b/utils/libmach/access.c index 6a58cdea..e054839e 100644 --- a/utils/libmach/access.c +++ b/utils/libmach/access.c @@ -6,16 +6,35 @@ #include <bio.h> #include "mach.h" -static int mget(Map*, ulong, char*, int); -static int mput(Map*, ulong, char*, int); -struct segment* reloc(Map*, ulong, long*); +static int mget(Map*, uvlong, void*, int); +static int mput(Map*, uvlong, void*, int); +static struct segment* reloc(Map*, uvlong, vlong*); /* * routines to get/put various types */ +int +geta(Map *map, uvlong addr, uvlong *x) +{ + ulong l; + uvlong vl; + + if (mach->szaddr == 8){ + if (get8(map, addr, &vl) < 0) + return -1; + *x = vl; + return 1; + } + + if (get4(map, addr, &l) < 0) + return -1; + *x = l; + + return 1; +} int -get8(Map *map, ulong addr, vlong *x) +get8(Map *map, uvlong addr, uvlong *x) { if (!map) { werrstr("get8: invalid map"); @@ -23,17 +42,17 @@ get8(Map *map, ulong addr, vlong *x) } if (map->nsegs == 1 && map->seg[0].fd < 0) { - *x = (vlong)addr; + *x = addr; return 1; } - if (mget(map, addr, (char *)x, 8) < 0) + if (mget(map, addr, x, 8) < 0) return -1; *x = machdata->swav(*x); - return (1); + return 1; } int -get4(Map *map, ulong addr, long *x) +get4(Map *map, uvlong addr, ulong *x) { if (!map) { werrstr("get4: invalid map"); @@ -44,14 +63,14 @@ get4(Map *map, ulong addr, long *x) *x = addr; return 1; } - if (mget(map, addr, (char *)x, 4) < 0) + if (mget(map, addr, x, 4) < 0) return -1; *x = machdata->swal(*x); - return (1); + return 1; } int -get2(Map *map, ulong addr, ushort *x) +get2(Map *map, uvlong addr, ushort *x) { if (!map) { werrstr("get2: invalid map"); @@ -62,14 +81,14 @@ get2(Map *map, ulong addr, ushort *x) *x = addr; return 1; } - if (mget(map, addr, (char *)x, 2) < 0) + if (mget(map, addr, x, 2) < 0) return -1; *x = machdata->swab(*x); - return (1); + return 1; } int -get1(Map *map, ulong addr, uchar *x, int size) +get1(Map *map, uvlong addr, uchar *x, int size) { uchar *cp; @@ -85,61 +104,103 @@ get1(Map *map, ulong addr, uchar *x, int size) while (size-- > 0) *x++ = 0; } else - return mget(map, addr, (char*)x, size); + return mget(map, addr, x, size); return 1; } int -put8(Map *map, ulong addr, vlong v) +puta(Map *map, uvlong addr, uvlong v) +{ + if (mach->szaddr == 8) + return put8(map, addr, v); + + return put4(map, addr, v); +} + +int +put8(Map *map, uvlong addr, uvlong v) { if (!map) { werrstr("put8: invalid map"); return -1; } v = machdata->swav(v); - return mput(map, addr, (char *)&v, 8); + return mput(map, addr, &v, 8); } int -put4(Map *map, ulong addr, long v) +put4(Map *map, uvlong addr, ulong v) { if (!map) { werrstr("put4: invalid map"); return -1; } v = machdata->swal(v); - return mput(map, addr, (char *)&v, 4); + return mput(map, addr, &v, 4); } int -put2(Map *map, ulong addr, ushort v) +put2(Map *map, uvlong addr, ushort v) { if (!map) { werrstr("put2: invalid map"); return -1; } v = machdata->swab(v); - return mput(map, addr, (char *)&v, 2); + return mput(map, addr, &v, 2); } int -put1(Map *map, ulong addr, uchar *v, int size) +put1(Map *map, uvlong addr, uchar *v, int size) { if (!map) { werrstr("put1: invalid map"); return -1; } - return mput(map, addr, (char *)v, size); + return mput(map, addr, v, size); +} + +static int +spread(struct segment *s, void *buf, int n, uvlong off) +{ + uvlong base; + + static struct { + struct segment *s; + char a[8192]; + uvlong off; + } cache; + + if(s->cache){ + base = off&~(sizeof cache.a-1); + if(cache.s != s || cache.off != base){ + cache.off = ~0; + if(seek(s->fd, base, 0) >= 0 + && readn(s->fd, cache.a, sizeof cache.a) == sizeof cache.a){ + cache.s = s; + cache.off = base; + } + } + if(cache.s == s && cache.off == base){ + off &= sizeof cache.a-1; + if(off+n > sizeof cache.a) + n = sizeof cache.a - off; + memmove(buf, cache.a+off, n); + return n; + } + } + + return pread(s->fd, buf, n, off); } static int -mget(Map *map, ulong addr, char *buf, int size) +mget(Map *map, uvlong addr, void *buf, int size) { - long off; + uvlong off; int i, j, k; struct segment *s; - s = reloc(map, addr, &off); + s = reloc(map, addr, (vlong*)&off); if (!s) return -1; if (s->fd < 0) { @@ -148,25 +209,24 @@ mget(Map *map, ulong addr, char *buf, int size) } if (s->mget) return s->mget(s, addr, off, buf, size); - seek(s->fd, off, 0); for (i = j = 0; i < 2; i++) { /* in case read crosses page */ - k = read(s->fd, buf, size-j); + k = spread(s, (void*)((uchar *)buf+j), size-j, off+j); if (k < 0) { - werrstr("can't read address %lux: %r", addr); + werrstr("can't read address %llux: %r", addr); return -1; } j += k; if (j == size) return j; } - werrstr("partial read at address %lux", addr); + werrstr("partial read at address %llux (size %d j %d)", addr, size, j); return -1; } static int -mput(Map *map, ulong addr, char *buf, int size) +mput(Map *map, uvlong addr, void *buf, int size) { - long off; + vlong off; int i, j, k; struct segment *s; @@ -184,22 +244,22 @@ mput(Map *map, ulong addr, char *buf, int size) for (i = j = 0; i < 2; i++) { /* in case read crosses page */ k = write(s->fd, buf, size-j); if (k < 0) { - werrstr("can't write address %lux: %r", addr); + werrstr("can't write address %llux: %r", addr); return -1; } j += k; if (j == size) return j; } - werrstr("partial write at address %lux", addr); + werrstr("partial write at address %llux", addr); return -1; } /* * convert address to file offset; returns nonzero if ok */ -struct segment* -reloc(Map *map, ulong addr, long *offp) +static struct segment* +reloc(Map *map, uvlong addr, vlong *offp) { int i; @@ -210,6 +270,6 @@ reloc(Map *map, ulong addr, long *offp) return &map->seg[i]; } } - werrstr("can't translate address %lux", addr); + werrstr("can't translate address %llux", addr); return 0; } diff --git a/utils/libmach/ar.h b/utils/libmach/ar.h index 71ffff12..cd538fab 100644 --- a/utils/libmach/ar.h +++ b/utils/libmach/ar.h @@ -14,5 +14,4 @@ struct ar_hdr char size[10]; char fmag[2]; }; -#define SAR_HDR 60 - +#define SAR_HDR (SARNAME+44) diff --git a/utils/libmach/bootexec.h b/utils/libmach/bootexec.h index a844ec7c..b401d394 100644 --- a/utils/libmach/bootexec.h +++ b/utils/libmach/bootexec.h @@ -33,12 +33,10 @@ struct mipsexec long data_start; /* base of data used for this file */ long bss_start; /* base of bss used for this file */ long gprmask; /* general purpose register mask */ -union{ - long mcprmask[4]; /* co-processor register masks */ - long mpcsize; -} u0; + long cprmask[4]; /* co-processor register masks */ long gp_value; /* the gp value used for this object */ }; +#define pcsize cprmask[0] struct mips4kexec { @@ -136,37 +134,3 @@ struct i386exec struct coffsect icomments; }; -struct i960exec -{ - struct i960coff{ - ulong i6sectmagic; - ulong i6time; - ulong i6syms; - ulong i6nsyms; - ulong i6opthdrflags; - }i6coff; - struct i960hdr{ - ulong i6magic; - ulong i6textsize; - ulong i6datasize; - ulong i6bsssize; - ulong i6entry; - ulong i6textstart; - ulong i6datastart; - ulong i6tagentries; - }i6hdr; - struct i960sect{ - char name[8]; - ulong phys; - ulong virt; - ulong size; - ulong fptr; - ulong fptrreloc; - ulong fptrlineno; - ulong nrelocnlineno; - ulong flags; - ulong align; - }i6texts; - struct i960sect i6datas; -}; - diff --git a/utils/libmach/elf.h b/utils/libmach/elf.h index b182135b..5d755b7a 100644 --- a/utils/libmach/elf.h +++ b/utils/libmach/elf.h @@ -2,20 +2,20 @@ * Definitions needed for accessing Irix ELF headers */ typedef struct { - unsigned char ident[16]; /* ident bytes */ - ushort type; /* file type */ - ushort machine; /* target machine */ - int version; /* file version */ - ulong elfentry; /* start address */ - ulong phoff; /* phdr file offset */ - ulong shoff; /* shdr file offset */ - int flags; /* file flags */ - ushort ehsize; /* sizeof ehdr */ - ushort phentsize; /* sizeof phdr */ - ushort phnum; /* number phdrs */ - ushort shentsize; /* sizeof shdr */ - ushort shnum; /* number shdrs */ - ushort shstrndx; /* shdr string index */ + uchar ident[16]; /* ident bytes */ + ushort type; /* file type */ + ushort machine; /* target machine */ + int version; /* file version */ + ulong elfentry; /* start address */ + ulong phoff; /* phdr file offset */ + ulong shoff; /* shdr file offset */ + int flags; /* file flags */ + ushort ehsize; /* sizeof ehdr */ + ushort phentsize; /* sizeof phdr */ + ushort phnum; /* number phdrs */ + ushort shentsize; /* sizeof shdr */ + ushort shnum; /* number shdrs */ + ushort shstrndx; /* shdr string index */ } Ehdr; typedef struct { @@ -78,7 +78,9 @@ enum { I860 = 7, /* Intel i860 */ MIPS = 8, /* Mips R2000 */ S370 = 9, /* Amdhal */ + SPARC64 = 18, /* Sun SPARC v9 */ POWER = 20, /* PowerPC */ + ARM = 40, /* ARM */ AMD64 = 62, /* Amd64 */ NO_VERSION = 0, /* version, ident[VERSION] */ @@ -96,6 +98,15 @@ enum { R = 0x4, /* flags */ W = 0x2, X = 0x1, + + /* Shdr Codes */ + Progbits = 1, /* section types */ + Strtab = 3, + Nobits = 8, + + Swrite = 1, /* section attributes */ + Salloc = 2, + Sexec = 4, }; #define ELF_MAG ((0x7f<<24) | ('E'<<16) | ('L'<<8) | 'F') diff --git a/utils/libmach/executable.c b/utils/libmach/executable.c index a17d6ae2..12099593 100644 --- a/utils/libmach/executable.c +++ b/utils/libmach/executable.c @@ -1,6 +1,6 @@ #include <lib9.h> #include <bio.h> -#include "bootexec.h" +#include <bootexec.h> #include "mach.h" #include "elf.h" @@ -11,14 +11,18 @@ typedef struct { union{ - Exec exec; /* in a.out.h */ - Ehdr ehdr; /* in elf.h */ - struct mipsexec mipsexec; - struct mips4kexec mips4kexec; - struct sparcexec sparcexec; - struct nextexec nextexec; + Exec exec; + struct { + u32int ohdr[8]; /* Exec */ + uvlong hdr[1]; + } exechdr64; + Ehdr elfhdr32; /* elf.h */ + struct mipsexec mips; /* bootexec.h */ + struct mips4kexec mips4k; /* bootexec.h */ + struct sparcexec sparc; /* bootexec.h */ + struct nextexec next; /* bootexec.h */ } e; - long dummy; /* padding to ensure extra long */ + u32int dummy; /* padding to ensure extra u32int */ } ExecHdr; static int nextboot(int, Fhdr*, ExecHdr*); @@ -26,14 +30,15 @@ static int sparcboot(int, Fhdr*, ExecHdr*); static int mipsboot(int, Fhdr*, ExecHdr*); static int mips4kboot(int, Fhdr*, ExecHdr*); static int common(int, Fhdr*, ExecHdr*); +static int commonllp64(int, Fhdr*, ExecHdr*); static int adotout(int, Fhdr*, ExecHdr*); static int elfdotout(int, Fhdr*, ExecHdr*); static int armdotout(int, Fhdr*, ExecHdr*); -static void setsym(Fhdr*, long, long, long, long); -static void setdata(Fhdr*, long, long, long, long); -static void settext(Fhdr*, long, long, long, long); -static void hswal(long*, int, long(*)(long)); -static long _round(long, long); +static void setsym(Fhdr*, long, long, long, vlong); +static void setdata(Fhdr*, uvlong, long, vlong, long); +static void settext(Fhdr*, uvlong, uvlong, long, vlong); +static void hswal(void*, int, ulong(*)(ulong)); +static uvlong _round(uvlong, ulong); /* * definition of per-executable file type structures @@ -42,10 +47,12 @@ static long _round(long, long); typedef struct Exectable{ long magic; /* big-endian magic number of file */ char *name; /* executable identifier */ - int type; /* Internal code */ + char *dlmname; /* dynamically loadable module identifier */ + uchar type; /* Internal code */ + uchar _magic; /* _MAGIC() magic */ Mach *mach; /* Per-machine data */ - ulong hsize; /* header size */ - long (*swal)(long); /* beswal or leswal */ + long hsize; /* header size */ + ulong (*swal)(ulong); /* beswal or leswal */ int (*hparse)(int, Fhdr*, ExecHdr*); } ExecTable; @@ -55,115 +62,172 @@ extern Mach mmips2be; extern Mach msparc; extern Mach m68020; extern Mach mi386; +extern Mach mamd64; extern Mach marm; extern Mach mpower; +extern Mach mpower64; ExecTable exectab[] = { { V_MAGIC, /* Mips v.out */ - "mips plan 9 executable", + "mips plan 9 executable BE", + "mips plan 9 dlm BE", FMIPS, + 1, + &mmips, + sizeof(Exec), + beswal, + adotout }, + { P_MAGIC, /* Mips 0.out (r3k le) */ + "mips plan 9 executable LE", + "mips plan 9 dlm LE", + FMIPSLE, + 1, &mmips, sizeof(Exec), beswal, adotout }, { M_MAGIC, /* Mips 4.out */ "mips 4k plan 9 executable BE", + "mips 4k plan 9 dlm BE", FMIPS2BE, + 1, &mmips2be, sizeof(Exec), beswal, adotout }, { N_MAGIC, /* Mips 0.out */ "mips 4k plan 9 executable LE", + "mips 4k plan 9 dlm LE", FMIPS2LE, + 1, &mmips2le, sizeof(Exec), beswal, adotout }, { 0x160<<16, /* Mips boot image */ "mips plan 9 boot image", + nil, FMIPSB, + 0, &mmips, sizeof(struct mipsexec), beswal, mipsboot }, { (0x160<<16)|3, /* Mips boot image */ "mips 4k plan 9 boot image", + nil, FMIPSB, - &mmips, + 0, + &mmips2be, sizeof(struct mips4kexec), beswal, mips4kboot }, { K_MAGIC, /* Sparc k.out */ "sparc plan 9 executable", + "sparc plan 9 dlm", FSPARC, + 1, &msparc, sizeof(Exec), beswal, adotout }, { 0x01030107, /* Sparc boot image */ "sparc plan 9 boot image", + nil, FSPARCB, + 0, &msparc, sizeof(struct sparcexec), beswal, sparcboot }, { A_MAGIC, /* 68020 2.out & boot image */ "68020 plan 9 executable", + "68020 plan 9 dlm", F68020, + 1, &m68020, sizeof(Exec), beswal, common }, { 0xFEEDFACE, /* Next boot image */ "next plan 9 boot image", + nil, FNEXTB, + 0, &m68020, sizeof(struct nextexec), beswal, nextboot }, { I_MAGIC, /* I386 8.out & boot image */ "386 plan 9 executable", + "386 plan 9 dlm", FI386, + 1, &mi386, sizeof(Exec), beswal, common }, - { ELF_MAG, - "Irix 5.X Elf executable", - FMIPS, - &mmips, - sizeof(Ehdr), + { S_MAGIC, /* amd64 6.out & boot image */ + "amd64 plan 9 executable", + "amd64 plan 9 dlm", + FAMD64, + 1, + &mamd64, + sizeof(Exec)+8, + nil, + commonllp64 }, + { Q_MAGIC, /* PowerPC q.out & boot image */ + "power plan 9 executable", + "power plan 9 dlm", + FPOWER, + 1, + &mpower, + sizeof(Exec), beswal, + common }, + { T_MAGIC, /* power64 9.out & boot image */ + "power64 plan 9 executable", + "power64 plan 9 dlm", + FPOWER64, + 1, + &mpower64, + sizeof(Exec)+8, + nil, + commonllp64 }, + { ELF_MAG, /* any elf32 */ + "elf executable", + nil, + FNONE, + 0, + &mi386, + sizeof(Ehdr), + nil, elfdotout }, - { E_MAGIC, /* Arm 5.out */ - "Arm plan 9 executable", + { E_MAGIC, /* Arm 5.out and boot image */ + "arm plan 9 executable", + "arm plan 9 dlm", FARM, + 1, &marm, sizeof(Exec), beswal, common }, { (143<<16)|0413, /* (Free|Net)BSD Arm */ - "Arm *BSD executable", + "arm *bsd executable", + nil, FARM, + 0, &marm, sizeof(Exec), leswal, armdotout }, - { Q_MAGIC, /* PowerPC q.out */ - "power plan 9 executable", - FPOWER, - &mpower, - sizeof(Exec), - beswal, - common }, { 0 }, }; -Mach *mach = &mmips; /* Global current machine table */ +Mach *mach = &mi386; /* Global current machine table */ -ExecTable* +static ExecTable* couldbe4k(ExecTable *mp) { Dir *d; @@ -184,13 +248,13 @@ couldbe4k(ExecTable *mp) return mp; } - int crackhdr(int fd, Fhdr *fp) { ExecTable *mp; ExecHdr d; - int nb, magic, ret; + int nb, ret; + ulong magic; fp->type = FNONE; nb = read(fd, (char *)&d.e, sizeof(d.e)); @@ -198,37 +262,67 @@ crackhdr(int fd, Fhdr *fp) return 0; ret = 0; - fp->magic = magic = beswal(d.e.exec.magic); /* big-endian */ + magic = beswal(d.e.exec.magic); /* big-endian */ for (mp = exectab; mp->magic; mp++) { - if (mp->magic == magic && nb >= mp->hsize) { + if (nb < mp->hsize) + continue; + + /* + * The.exec.magic number has morphed into something + * with fields (the straw was DYN_MAGIC) so now + * a flag is needed in Fhdr to distinguish _MAGIC() + * magic numbers from foreign magic numbers. + * + * This code is creaking a bit and if it has to + * be modified/extended much more it's probably + * time to step back and redo it all. + */ + if(mp->_magic){ + if(mp->magic != (magic & ~DYN_MAGIC)) + continue; + if(mp->magic == V_MAGIC) mp = couldbe4k(mp); - hswal((long *) &d, sizeof(d.e)/sizeof(long), mp->swal); - fp->type = mp->type; + if ((magic & DYN_MAGIC) && mp->dlmname != nil) + fp->name = mp->dlmname; + else + fp->name = mp->name; + } + else{ + if(mp->magic != magic) + continue; fp->name = mp->name; - fp->hdrsz = mp->hsize; /* zero on bootables */ - mach = mp->mach; - ret = mp->hparse(fd, fp, &d); - seek(fd, mp->hsize, 0); /* seek to end of header */ - break; } + fp->type = mp->type; + fp->hdrsz = mp->hsize; /* will be zero on bootables */ + fp->_magic = mp->_magic; + fp->magic = magic; + + mach = mp->mach; + if(mp->swal != nil) + hswal(&d, sizeof(d.e)/sizeof(ulong), mp->swal); + ret = mp->hparse(fd, fp, &d); + seek(fd, mp->hsize, 0); /* seek to end of header */ + break; } if(mp->magic == 0) werrstr("unknown header type"); return ret; } + /* * Convert header to canonical form */ static void -hswal(long *lp, int n, long (*swap) (long)) +hswal(void *v, int n, ulong (*swap)(ulong)) { - while (n--) { - *lp = (*swap) (*lp); - lp++; - } + ulong *ulp; + + for(ulp = v; n--; ulp++) + *ulp = (*swap)(*ulp); } + /* * Crack a normal a.out-type header */ @@ -247,57 +341,103 @@ adotout(int fd, Fhdr *fp, ExecHdr *hp) return 1; } +static void +commonboot(Fhdr *fp) +{ + if (!(fp->entry & mach->ktmask)) + return; + + switch(fp->type) { /* boot image */ + case F68020: + fp->type = F68020B; + fp->name = "68020 plan 9 boot image"; + break; + case FI386: + fp->type = FI386B; + fp->txtaddr = (u32int)fp->entry; + fp->name = "386 plan 9 boot image"; + fp->dataddr = _round(fp->txtaddr+fp->txtsz, mach->pgsize); + break; + case FARM: + fp->type = FARMB; + fp->txtaddr = (u32int)fp->entry; + fp->name = "ARM plan 9 boot image"; + fp->dataddr = _round(fp->txtaddr+fp->txtsz, mach->pgsize); + return; + case FALPHA: + fp->type = FALPHAB; + fp->txtaddr = (u32int)fp->entry; + fp->name = "alpha plan 9 boot image"; + fp->dataddr = fp->txtaddr+fp->txtsz; + break; + case FPOWER: + fp->type = FPOWERB; + fp->txtaddr = (u32int)fp->entry; + fp->name = "power plan 9 boot image"; + fp->dataddr = fp->txtaddr+fp->txtsz; + break; + case FAMD64: + fp->type = FAMD64B; + fp->txtaddr = fp->entry; + fp->name = "amd64 plan 9 boot image"; + fp->dataddr = _round(fp->txtaddr+fp->txtsz, mach->pgsize); + break; + default: + return; + } + fp->hdrsz = 0; /* header stripped */ +} + /* - * 68020 2.out and 68020 bootable images - * 386I 8.out and 386I bootable images + * _MAGIC() style headers and + * alpha plan9-style bootable images for axp "headerless" boot * */ static int common(int fd, Fhdr *fp, ExecHdr *hp) { - long kbase; - adotout(fd, fp, hp); - kbase = mach->kbase; - if ((fp->entry & kbase) == kbase) { /* Boot image */ - switch(fp->type) { - case F68020: - fp->type = F68020B; - fp->name = "68020 plan 9 boot image"; - fp->hdrsz = 0; /* header stripped */ - break; - case FI386: - fp->type = FI386B; - fp->txtaddr = sizeof(Exec); - fp->name = "386 plan 9 boot image"; - fp->hdrsz = 0; /* header stripped */ - fp->dataddr = fp->txtaddr+fp->txtsz; - break; - case FARM: - fp->txtaddr = kbase+0x8000+sizeof(Exec); - fp->name = "ARM plan 9 boot image"; - fp->hdrsz = 0; /* header stripped */ - fp->dataddr = fp->txtaddr+fp->txtsz; - return 1; - default: - break; - } - fp->txtaddr |= kbase; - fp->entry |= kbase; - fp->dataddr |= kbase; - } - else if (fp->type == FARM && (fp->entry == 0x8020 || fp->entry == 0x8080)) { - fp->txtaddr = fp->entry; - fp->name = "ARM Inferno boot image"; - fp->hdrsz = 0; /* header stripped */ - fp->dataddr = fp->txtaddr+fp->txtsz; + if(hp->e.exec.magic & DYN_MAGIC) { + fp->txtaddr = 0; + fp->dataddr = fp->txtsz; + return 1; } - else if (fp->type == FPOWER && fp->entry == 0x3020) { - fp->txtaddr = fp->entry; - fp->name = "Power Inferno boot image"; - fp->hdrsz = 0; /* header stripped */ - fp->dataddr = fp->txtaddr+fp->txtsz; + commonboot(fp); + return 1; +} + +static int +commonllp64(int, Fhdr *fp, ExecHdr *hp) +{ + long pgsize; + uvlong entry; + + hswal(&hp->e, sizeof(Exec)/sizeof(long), beswal); + if(!(hp->e.exec.magic & HDR_MAGIC)) + return 0; + + /* + * There can be more.exec.magic here if the + * header ever needs more expansion. + * For now just catch use of any of the + * unused bits. + */ + if((hp->e.exec.magic & ~DYN_MAGIC)>>16) + return 0; + entry = beswav(hp->e.exechdr64.hdr[0]); + + pgsize = mach->pgsize; + settext(fp, entry, pgsize+fp->hdrsz, hp->e.exec.text, fp->hdrsz); + setdata(fp, _round(pgsize+fp->txtsz+fp->hdrsz, pgsize), + hp->e.exec.data, fp->txtsz+fp->hdrsz, hp->e.exec.bss); + setsym(fp, hp->e.exec.syms, hp->e.exec.spsz, hp->e.exec.pcsz, fp->datoff+fp->datsz); + + if(hp->e.exec.magic & DYN_MAGIC) { + fp->txtaddr = 0; + fp->dataddr = fp->txtsz; + return 1; } + commonboot(fp); return 1; } @@ -308,24 +448,24 @@ static int mipsboot(int fd, Fhdr *fp, ExecHdr *hp) { USED(fd); - switch(hp->e.mipsexec.amagic) { + fp->type = FMIPSB; + switch(hp->e.mips.amagic) { default: case 0407: /* some kind of mips */ - fp->type = FMIPSB; - settext(fp, hp->e.mipsexec.mentry, hp->e.mipsexec.text_start, hp->e.mipsexec.tsize, - sizeof(struct mipsexec)+4); - setdata(fp, hp->e.mipsexec.data_start, hp->e.mipsexec.dsize, - fp->txtoff+hp->e.mipsexec.tsize, hp->e.mipsexec.bsize); + settext(fp, (u32int)hp->e.mips.mentry, (u32int)hp->e.mips.text_start, + hp->e.mips.tsize, sizeof(struct mipsexec)+4); + setdata(fp, (u32int)hp->e.mips.data_start, hp->e.mips.dsize, + fp->txtoff+hp->e.mips.tsize, hp->e.mips.bsize); break; case 0413: /* some kind of mips */ - fp->type = FMIPSB; - settext(fp, hp->e.mipsexec.mentry, hp->e.mipsexec.text_start, hp->e.mipsexec.tsize, 0); - setdata(fp, hp->e.mipsexec.data_start, hp->e.mipsexec.dsize, hp->e.mipsexec.tsize, - hp->e.mipsexec.bsize); + settext(fp, (u32int)hp->e.mips.mentry, (u32int)hp->e.mips.text_start, + hp->e.mips.tsize, 0); + setdata(fp, (u32int)hp->e.mips.data_start, hp->e.mips.dsize, + hp->e.mips.tsize, hp->e.mips.bsize); break; } - setsym(fp, hp->e.mipsexec.nsyms, 0, hp->e.mipsexec.u0.mpcsize, hp->e.mipsexec.symptr); - fp->hdrsz = 0; /* header stripped */ + setsym(fp, hp->e.mips.nsyms, 0, hp->e.mips.pcsize, hp->e.mips.symptr); + fp->hdrsz = 0; /* header stripped */ return 1; } @@ -336,24 +476,24 @@ static int mips4kboot(int fd, Fhdr *fp, ExecHdr *hp) { USED(fd); - switch(hp->e.mipsexec.amagic) { + fp->type = FMIPSB; + switch(hp->e.mips4k.h.amagic) { default: case 0407: /* some kind of mips */ - fp->type = FMIPSB; - settext(fp, hp->e.mipsexec.mentry, hp->e.mipsexec.text_start, hp->e.mipsexec.tsize, - sizeof(struct mips4kexec)); - setdata(fp, hp->e.mipsexec.data_start, hp->e.mipsexec.dsize, - fp->txtoff+hp->e.mipsexec.tsize, hp->e.mipsexec.bsize); + settext(fp, (u32int)hp->e.mips4k.h.mentry, (u32int)hp->e.mips4k.h.text_start, + hp->e.mips4k.h.tsize, sizeof(struct mips4kexec)); + setdata(fp, (u32int)hp->e.mips4k.h.data_start, hp->e.mips4k.h.dsize, + fp->txtoff+hp->e.mips4k.h.tsize, hp->e.mips4k.h.bsize); break; case 0413: /* some kind of mips */ - fp->type = FMIPSB; - settext(fp, hp->e.mipsexec.mentry, hp->e.mipsexec.text_start, hp->e.mipsexec.tsize, 0); - setdata(fp, hp->e.mipsexec.data_start, hp->e.mipsexec.dsize, hp->e.mipsexec.tsize, - hp->e.mipsexec.bsize); + settext(fp, (u32int)hp->e.mips4k.h.mentry, (u32int)hp->e.mips4k.h.text_start, + hp->e.mips4k.h.tsize, 0); + setdata(fp, (u32int)hp->e.mips4k.h.data_start, hp->e.mips4k.h.dsize, + hp->e.mips4k.h.tsize, hp->e.mips4k.h.bsize); break; } - setsym(fp, hp->e.mipsexec.nsyms, 0, hp->e.mipsexec.u0.mpcsize, hp->e.mipsexec.symptr); - fp->hdrsz = 0; /* header stripped */ + setsym(fp, hp->e.mips4k.h.nsyms, 0, hp->e.mips4k.h.pcsize, hp->e.mips4k.h.symptr); + fp->hdrsz = 0; /* header stripped */ return 1; } @@ -365,12 +505,12 @@ sparcboot(int fd, Fhdr *fp, ExecHdr *hp) { USED(fd); fp->type = FSPARCB; - settext(fp, hp->e.sparcexec.sentry, hp->e.sparcexec.sentry, hp->e.sparcexec.stext, - sizeof(struct sparcexec)); - setdata(fp, hp->e.sparcexec.sentry+hp->e.sparcexec.stext, hp->e.sparcexec.sdata, - fp->txtoff+hp->e.sparcexec.stext, hp->e.sparcexec.sbss); - setsym(fp, hp->e.sparcexec.ssyms, 0, hp->e.sparcexec.sdrsize, fp->datoff+hp->e.sparcexec.sdata); - fp->hdrsz = 0; /* header stripped */ + settext(fp, hp->e.sparc.sentry, hp->e.sparc.sentry, hp->e.sparc.stext, + sizeof(struct sparcexec)); + setdata(fp, hp->e.sparc.sentry+hp->e.sparc.stext, hp->e.sparc.sdata, + fp->txtoff+hp->e.sparc.stext, hp->e.sparc.sbss); + setsym(fp, hp->e.sparc.ssyms, 0, hp->e.sparc.sdrsize, fp->datoff+hp->e.sparc.sdata); + fp->hdrsz = 0; /* header stripped */ return 1; } @@ -382,129 +522,150 @@ nextboot(int fd, Fhdr *fp, ExecHdr *hp) { USED(fd); fp->type = FNEXTB; - settext(fp, hp->e.nextexec.textc.vmaddr, hp->e.nextexec.textc.vmaddr, - hp->e.nextexec.texts.size, hp->e.nextexec.texts.offset); - setdata(fp, hp->e.nextexec.datac.vmaddr, hp->e.nextexec.datas.size, - hp->e.nextexec.datas.offset, hp->e.nextexec.bsss.size); - setsym(fp, hp->e.nextexec.symc.nsyms, hp->e.nextexec.symc.spoff, hp->e.nextexec.symc.pcoff, - hp->e.nextexec.symc.symoff); - fp->hdrsz = 0; /* header stripped */ + settext(fp, hp->e.next.textc.vmaddr, hp->e.next.textc.vmaddr, + hp->e.next.texts.size, hp->e.next.texts.offset); + setdata(fp, hp->e.next.datac.vmaddr, hp->e.next.datas.size, + hp->e.next.datas.offset, hp->e.next.bsss.size); + setsym(fp, hp->e.next.symc.nsyms, hp->e.next.symc.spoff, hp->e.next.symc.pcoff, + hp->e.next.symc.symoff); + fp->hdrsz = 0; /* header stripped */ return 1; } -static Shdr* -elfsectbyname(int fd, Ehdr *hp, Shdr *sp, char *name) -{ - int i, offset, n; - char s[64]; - - offset = sp[hp->shstrndx].offset; - for(i = 1; i < hp->shnum; i++) { - seek(fd, offset+sp[i].name, 0); - n = read(fd, s, sizeof(s)-1); - if(n < 0) - continue; - s[n] = 0; - if(strcmp(s, name) == 0) - return &sp[i]; - } - return 0; -} /* - * Decode an Irix 5.x ELF header + * Elf32 binaries. */ static int elfdotout(int fd, Fhdr *fp, ExecHdr *hp) { + ulong (*swal)(ulong); + ushort (*swab)(ushort); Ehdr *ep; - Shdr *es, *txt, *init, *s; - long addr, size, offset, bsize; - - ep = &hp->e.ehdr; - fp->magic = ELF_MAG; - fp->hdrsz = (ep->ehsize+ep->phnum*ep->phentsize+16)&~15; + Phdr *ph; + int i, it, id, is, phsz; - if(ep->shnum <= 0) { - werrstr("no ELF header sections"); + /* bitswap the header according to the DATA format */ + ep = &hp->e.elfhdr32; + if(ep->ident[CLASS] != ELFCLASS32) { + werrstr("bad ELF class - not 32 bit"); return 0; } - es = malloc(sizeof(Shdr)*ep->shnum); - if(es == 0) + if(ep->ident[DATA] == ELFDATA2LSB) { + swab = leswab; + swal = leswal; + } else if(ep->ident[DATA] == ELFDATA2MSB) { + swab = beswab; + swal = beswal; + } else { + werrstr("bad ELF encoding - not big or little endian"); return 0; + } - seek(fd, ep->shoff, 0); - if(read(fd, es, sizeof(Shdr)*ep->shnum) < 0){ - free(es); + ep->type = swab(ep->type); + ep->machine = swab(ep->machine); + ep->version = swal(ep->version); + ep->elfentry = swal(ep->elfentry); + ep->phoff = swal(ep->phoff); + ep->shoff = swal(ep->shoff); + ep->flags = swal(ep->flags); + ep->ehsize = swab(ep->ehsize); + ep->phentsize = swab(ep->phentsize); + ep->phnum = swab(ep->phnum); + ep->shentsize = swab(ep->shentsize); + ep->shnum = swab(ep->shnum); + ep->shstrndx = swab(ep->shstrndx); + if(ep->type != EXEC || ep->version != CURRENT) return 0; - } - txt = elfsectbyname(fd, ep, es, ".text"); - init = elfsectbyname(fd, ep, es, ".init"); - if(txt == 0 || init == 0 || init != txt+1) - goto bad; - if(txt->addr+txt->size != init->addr) - goto bad; - settext(fp, ep->elfentry, txt->addr, txt->size+init->size, txt->offset); - - addr = 0; - offset = 0; - size = 0; - s = elfsectbyname(fd, ep, es, ".data"); - if(s) { - addr = s->addr; - size = s->size; - offset = s->offset; + /* we could definitely support a lot more machines here */ + fp->magic = ELF_MAG; + fp->hdrsz = (ep->ehsize+ep->phnum*ep->phentsize+16)&~15; + switch(ep->machine) { + case I386: + mach = &mi386; + fp->type = FI386; + break; + case MIPS: + mach = &mmips; + fp->type = FMIPS; + break; + case SPARC64: + return 0; + case POWER: + mach = &mpower; + fp->type = FPOWER; + break; + case AMD64: + mach = &mamd64; + fp->type = FAMD64; + break; + default: + return 0; } - s = elfsectbyname(fd, ep, es, ".rodata"); - if(s) { - if(addr){ - if(addr+size != s->addr) - goto bad; - } else { - addr = s->addr; - offset = s->offset; - } - size += s->size; + if(ep->phentsize != sizeof(Phdr)) { + werrstr("bad ELF header size"); + return 0; } - - s = elfsectbyname(fd, ep, es, ".got"); - if(s) { - if(addr){ - if(addr+size != s->addr) - goto bad; - } else { - addr = s->addr; - offset = s->offset; - } - size += s->size; + phsz = sizeof(Phdr)*ep->phnum; + ph = malloc(phsz); + if(!ph) + return 0; + seek(fd, ep->phoff, 0); + if(read(fd, ph, phsz) < 0) { + free(ph); + return 0; } - - bsize = 0; - s = elfsectbyname(fd, ep, es, ".bss"); - if(s) { - if(addr){ - if(addr+size != s->addr) - goto bad; - } else { - addr = s->addr; - offset = s->offset; - } - bsize = s->size; + hswal(ph, phsz/sizeof(ulong), swal); + + /* find text, data and symbols and install them */ + it = id = is = -1; + for(i = 0; i < ep->phnum; i++) { + if(ph[i].type == LOAD + && (ph[i].flags & (R|X)) == (R|X) && it == -1) + it = i; + else if(ph[i].type == LOAD + && (ph[i].flags & (R|W)) == (R|W) && id == -1) + id = i; + else if(ph[i].type == NOPTYPE && is == -1) + is = i; } + if(it == -1 || id == -1) { + /* + * The SPARC64 boot image is something of an ELF hack. + * Text+Data+BSS are represented by ph[0]. Symbols + * are represented by ph[1]: + * + * filesz, memsz, vaddr, paddr, off + * ph[0] : txtsz+datsz, txtsz+datsz+bsssz, txtaddr-KZERO, datasize, txtoff + * ph[1] : symsz, lcsz, 0, 0, symoff + */ + if(ep->machine == SPARC64 && ep->phnum == 2) { + ulong txtaddr, txtsz, dataddr, bsssz; + + txtaddr = ph[0].vaddr | 0x80000000; + txtsz = ph[0].filesz - ph[0].paddr; + dataddr = txtaddr + txtsz; + bsssz = ph[0].memsz - ph[0].filesz; + settext(fp, ep->elfentry | 0x80000000, txtaddr, txtsz, ph[0].offset); + setdata(fp, dataddr, ph[0].paddr, ph[0].offset + txtsz, bsssz); + setsym(fp, ph[1].filesz, 0, ph[1].memsz, ph[1].offset); + free(ph); + return 1; + } - if(addr == 0) - goto bad; + werrstr("No TEXT or DATA sections"); + free(ph); + return 0; + } - setdata(fp, addr, size, offset, bsize); - fp->name = "IRIX Elf a.out executable"; - free(es); + settext(fp, ep->elfentry, ph[it].vaddr, ph[it].memsz, ph[it].offset); + setdata(fp, ph[id].vaddr, ph[id].filesz, ph[id].offset, ph[id].memsz - ph[id].filesz); + if(is != -1) + setsym(fp, ph[is].filesz, 0, ph[is].memsz, ph[is].offset); + free(ph); return 1; -bad: - free(es); - werrstr("ELF sections scrambled"); - return 0; } /* @@ -513,7 +674,7 @@ bad: static int armdotout(int fd, Fhdr *fp, ExecHdr *hp) { - long kbase; + uvlong kbase; USED(fd); settext(fp, hp->e.exec.entry, sizeof(Exec), hp->e.exec.text, sizeof(Exec)); @@ -531,37 +692,39 @@ armdotout(int fd, Fhdr *fp, ExecHdr *hp) } static void -settext(Fhdr *fp, long e, long a, long s, long off) +settext(Fhdr *fp, uvlong e, uvlong a, long s, vlong off) { fp->txtaddr = a; fp->entry = e; fp->txtsz = s; fp->txtoff = off; } + static void -setdata(Fhdr *fp, long a, long s, long off, long bss) +setdata(Fhdr *fp, uvlong a, long s, vlong off, long bss) { fp->dataddr = a; fp->datsz = s; fp->datoff = off; fp->bsssz = bss; } + static void -setsym(Fhdr *fp, long sy, long sppc, long lnpc, long symoff) +setsym(Fhdr *fp, long symsz, long sppcsz, long lnpcsz, vlong symoff) { - fp->symsz = sy; + fp->symsz = symsz; fp->symoff = symoff; - fp->sppcsz = sppc; + fp->sppcsz = sppcsz; fp->sppcoff = fp->symoff+fp->symsz; - fp->lnpcsz = lnpc; + fp->lnpcsz = lnpcsz; fp->lnpcoff = fp->sppcoff+fp->sppcsz; } -static long -_round(long a, long b) +static uvlong +_round(uvlong a, ulong b) { - long w; + uvlong w; w = (a/b)*b; if (a!=w) diff --git a/utils/libmach/kdb.c b/utils/libmach/kdb.c index bffd5e77..eb52b3c2 100644 --- a/utils/libmach/kdb.c +++ b/utils/libmach/kdb.c @@ -7,10 +7,10 @@ */ static char *sparcexcep(Map*, Rgetter); -static int sparcfoll(Map*, ulong, Rgetter, ulong*); -static int sparcinst(Map*, ulong, char, char*, int); -static int sparcdas(Map*, ulong, char*, int); -static int sparcinstlen(Map*, ulong); +static int sparcfoll(Map*, uvlong, Rgetter, uvlong*); +static int sparcinst(Map*, uvlong, char, char*, int); +static int sparcdas(Map*, uvlong, char*, int); +static int sparcinstlen(Map*, uvlong); Machdata sparcmach = { @@ -85,16 +85,16 @@ sparcexcep(Map *map, Rgetter rget) /* Sparc disassembler and related functions */ -typedef struct instr Instr; - struct opcode { char *mnemonic; - void (*f)(Instr*, char*); + void (*f)(struct instr*, char*); int flag; }; static char FRAMENAME[] = ".frame"; +typedef struct instr Instr; + struct instr { uchar op; /* bits 31-30 */ uchar rd; /* bits 29-25 */ @@ -115,7 +115,7 @@ struct instr { int target; /* SETHI+ADD dest reg */ long w0; long w1; - ulong addr; /* pc of instruction */ + uvlong addr; /* pc of instruction */ char *curr; /* current fill level in output buffer */ char *end; /* end of buffer */ int size; /* number of longs in instr */ @@ -125,7 +125,7 @@ struct instr { static Map *mymap; /* disassembler context */ static int dascase; -static int mkinstr(ulong, Instr*); +static int mkinstr(uvlong, Instr*); static void bra1(Instr*, char*, char*[]); static void bra(Instr*, char*); static void fbra(Instr*, char*); @@ -150,140 +150,152 @@ static void loadcsr(Instr*, char*); static void trap(Instr*, char*); static struct opcode sparcop0[8] = { - "UNIMP", unimp, 0, /* page 137 */ /* 0 */ - "", 0, 0, /* 1 */ - "B", bra, 0, /* page 119 */ /* 2 */ - "", 0, 0, /* 3 */ - "SETHI", sethi, 0, /* page 104 */ /* 4 */ - "", 0, 0, /* 5 */ - "FB", fbra, 0, /* page 121 */ /* 6 */ - "CB", cbra, 0, /* page 123 */ /* 7 */ + [0] "UNIMP", unimp, 0, /* page 137 */ + [2] "B", bra, 0, /* page 119 */ + [4] "SETHI", sethi, 0, /* page 104 */ + [6] "FB", fbra, 0, /* page 121 */ + [7] "CB", cbra, 0, /* page 123 */ }; static struct opcode sparcop2[64] = { - "ADD", add, 0, /* page 108 */ /* 0x00 */ - "AND", add, 0, /* page 106 */ /* 0x01 */ - "OR", add, 0, /* 0x02 */ - "XOR", add, 0, /* 0x03 */ - "SUB", add, 0, /* page 110 */ /* 0x04 */ - "ANDN", add, 0, /* 0x05 */ - "ORN", add, 0, /* 0x06 */ - "XORN", add, 0, /* 0x07 */ - "ADDX", add, 0, /* 0x08 */ - "", 0, 0, /* 0x09 */ - "UMUL", add, 0, /* page 113 */ /* 0x0a */ - "SMUL", add, 0, /* 0x0b */ - "SUBX", add, 0, /* 0x0c */ - "", 0, 0, /* 0x0d */ - "UDIV", add, 0, /* page 115 */ /* 0x0e */ - "SDIV", add, 0, /* 0x0f */ - "ADDCC", add, 0, /* 0x10 */ - "ANDCC", add, 0, /* 0x11 */ - "ORCC", add, 0, /* 0x12 */ - "XORCC", add, 0, /* 0x13 */ - "SUBCC", cmp, 0, /* 0x14 */ - "ANDNCC", add, 0, /* 0x15 */ - "ORNCC", add, 0, /* 0x16 */ - "XORNCC", add, 0, /* 0x17 */ - "ADDXCC", add, 0, /* 0x18 */ - "", 0, 0, /* 0x19 */ - "UMULCC", add, 0, /* 0x1a */ - "SMULCC", add, 0, /* 0x1b */ - "SUBXCC", add, 0, /* 0x1c */ - "", 0, 0, /* 0x1d */ - "UDIVCC", add, 0, /* 0x1e */ - "SDIVCC", add, 0, /* 0x1f */ - "TADD", add, 0, /* page 109 */ /* 0x20 */ - "TSUB", add, 0, /* page 111 */ /* 0x21 */ - "TADDCCTV", add, 0, /* 0x22 */ - "TSUBCCTV", add, 0, /* 0x23 */ - "MULSCC", add, 0, /* page 112 */ /* 0x24 */ - "SLL", shift, 0, /* page 107 */ /* 0x25 */ - "SRL", shift, 0, /* 0x26 */ - "SRA", shift, 0, /* 0x27 */ - "rdy", rd, 0, /* page 131 */ /* 0x28 */ - "rdpsr", rd, 0, /* 0x29 */ - "rdwim", rd, 0, /* 0x2a */ - "rdtbr", rd, 0, /* 0x2b */ - "", 0, 0, /* 0x2c */ - "", 0, 0, /* 0x2d */ - "", 0, 0, /* 0x2e */ - "", 0, 0, /* 0x2f */ - "wry", wr, 0, /* page 133 */ /* 0x30 */ - "wrpsr", wr, 0, /* 0x31 */ - "wrwim", wr, 0, /* 0x32 */ - "wrtbr", wr, 0, /* 0x33 */ - "FPOP", fpop, 0, /* page 140 */ /* 0x34 */ - "FPOP", fpop, 0, /* 0x35 */ - "", 0, 0, /* 0x36 */ - "", 0, 0, /* 0x37 */ - "JMPL", jmpl, 0, /* page 126 */ /* 0x38 */ - "RETT", add, 0, /* page 127 */ /* 0x39 */ - "T", trap, 0, /* page 129 */ /* 0x3a */ - "flush", add, 0, /* page 138 */ /* 0x3b */ - "SAVE", add, 0, /* page 117 */ /* 0x3c */ - "RESTORE", add, 0, /* 0x3d */ + [0x00] "ADD", add, 0, /* page 108 */ + [0x10] "ADDCC", add, 0, + [0x08] "ADDX", add, 0, + [0x18] "ADDXCC", add, 0, + + [0x20] "TADD", add, 0, /* page 109 */ + [0x22] "TADDCCTV", add, 0, + + [0x04] "SUB", add, 0, /* page 110 */ + [0x14] "SUBCC", cmp, 0, + [0x0C] "SUBX", add, 0, + [0x1C] "SUBXCC", add, 0, + + [0x21] "TSUB", add, 0, /* page 111 */ + [0x23] "TSUBCCTV", add, 0, + + [0x24] "MULSCC", add, 0, /* page 112 */ + + [0x0A] "UMUL", add, 0, /* page 113 */ + [0x0B] "SMUL", add, 0, + [0x1A] "UMULCC", add, 0, + [0x1B] "SMULCC", add, 0, + + [0x0E] "UDIV", add, 0, /* page 115 */ + [0x0F] "SDIV", add, 0, + [0x1E] "UDIVCC", add, 0, + [0x1F] "SDIVCC", add, 0, + + [0x01] "AND", add, 0, /* page 106 */ + [0x11] "ANDCC", add, 0, + [0x05] "ANDN", add, 0, + [0x15] "ANDNCC", add, 0, + [0x02] "OR", add, 0, + [0x12] "ORCC", add, 0, + [0x06] "ORN", add, 0, + [0x16] "ORNCC", add, 0, + [0x03] "XOR", add, 0, + [0x13] "XORCC", add, 0, + [0x07] "XORN", add, 0, + [0x17] "XORNCC", add, 0, + + [0x25] "SLL", shift, 0, /* page 107 */ + [0x26] "SRL", shift, 0, + [0x27] "SRA", shift, 0, + + [0x3C] "SAVE", add, 0, /* page 117 */ + [0x3D] "RESTORE", add, 0, + + [0x38] "JMPL", jmpl, 0, /* page 126 */ + + [0x39] "RETT", add, 0, /* page 127 */ + + [0x3A] "T", trap, 0, /* page 129 */ + + [0x28] "rdy", rd, 0, /* page 131 */ + [0x29] "rdpsr", rd, 0, + [0x2A] "rdwim", rd, 0, + [0x2B] "rdtbr", rd, 0, + + [0x30] "wry", wr, 0, /* page 133 */ + [0x31] "wrpsr", wr, 0, + [0x32] "wrwim", wr, 0, + [0x33] "wrtbr", wr, 0, + + [0x3B] "flush", add, 0, /* page 138 */ + + [0x34] "FPOP", fpop, 0, /* page 140 */ + [0x35] "FPOP", fpop, 0, }; static struct opcode sparcop3[64]={ - "ld", load, 0, /* 0x00 */ - "ldub", load, 0, /* 0x01 */ - "lduh", load, 0, /* 0x02 */ - "ldd", load, 0, /* 0x03 */ - "st", store, 0, /* 0x04 */ - "stb", store, 0, /* page 95 */ /* 0x05 */ - "sth", store, 0, /* 0x06 */ - "std", store, 0, /* 0x07 */ - "", 0, 0, /* 0x08 */ - "ldsb", load, 0, /* page 90 */ /* 0x09 */ - "ldsh", load, 0, /* 0x0a */ - "", 0, 0, /* 0x0b */ - "", 0, 0, /* 0x0c */ - "ldstub", store, 0, /* page 101 */ /* 0x0d */ - "", 0, 0, /* 0x0e */ - "swap", load, 0, /* page 102 */ /* 0x0f */ - "lda", loada, 0, /* 0x10 */ - "lduba", loada, 0, /* 0x11 */ - "lduha", loada, 0, /* 0x12 */ - "ldda", loada, 0, /* 0x13 */ - "sta", storea, 0, /* 0x14 */ - "stba", storea, 0, /* 0x15 */ - "stha", storea, 0, /* 0x16 */ - "stda", storea, 0, /* 0x17 */ - "", 0, 0, /* 0x18 */ - "ldsba", loada, 0, /* 0x19 */ - "ldsha", loada, 0, /* 0x1a */ - "", 0, 0, /* 0x1b */ - "", 0, 0, /* 0x1c */ - "ldstuba", storea, 0, /* 0x1d */ - "", 0, 0, /* 0x1e */ - "swapa", loada, 0, /* 0x1f */ - "ldf", loadf, 0, /* page 92 */ /* 0x20 */ - "ldfsr", loadf,0, /* 0x21 */ - "", 0, 0, /* 0x22 */ - "lddf", loadf, 0, /* 0x23 */ - "stf", storef, 0, /* page 97 */ /* 0x24 */ - "stfsr", storef,0, /* 0x25 */ - "stdfq", storef,0, /* 0x26 */ - "stdf", storef, 0, /* 0x27 */ - "", 0, 0, /* 0x28 */ - "", 0, 0, /* 0x29 */ - "", 0, 0, /* 0x2a */ - "", 0, 0, /* 0x2b */ - "", 0, 0, /* 0x2c */ - "", 0, 0, /* 0x2d */ - "", 0, 0, /* 0x2e */ - "", 0, 0, /* 0x2f */ - "ldc", loadc, 0, /* page 94 */ /* 0x30 */ - "ldcsr", loadcsr,0, /* 0x31 */ - "", 0, 0, /* 0x32 */ - "lddc", loadc, 0, /* 0x33 */ - "stc", loadc, 0, /* page 99 */ /* 0x34 */ - "stcsr", loadcsr,0, /* 0x35 */ - "stdcq", loadcsr,0, /* 0x36 */ - "stdc", loadc, 0, /* 0x37 */ + [0x09] "ldsb", load, 0, /* page 90 */ + [0x19] "ldsba", loada, 0, + [0x0A] "ldsh", load, 0, + [0x1A] "ldsha", loada, 0, + [0x01] "ldub", load, 0, + [0x11] "lduba", loada, 0, + [0x02] "lduh", load, 0, + [0x12] "lduha", loada, 0, + [0x00] "ld", load, 0, + [0x10] "lda", loada, 0, + [0x03] "ldd", load, 0, + [0x13] "ldda", loada, 0, + + [0x20] "ldf", loadf, 0, /* page 92 */ + [0x23] "lddf", loadf, 0, + [0x21] "ldfsr", loadf,0, + + [0x30] "ldc", loadc, 0, /* page 94 */ + [0x33] "lddc", loadc, 0, + [0x31] "ldcsr", loadcsr,0, + + [0x05] "stb", store, 0, /* page 95 */ + [0x15] "stba", storea, 0, + [0x06] "sth", store, 0, + [0x16] "stha", storea, 0, + [0x04] "st", store, 0, + [0x14] "sta", storea, 0, + [0x07] "std", store, 0, + [0x17] "stda", storea, 0, + + [0x24] "stf", storef, 0, /* page 97 */ + [0x27] "stdf", storef, 0, + [0x25] "stfsr", storef,0, + [0x26] "stdfq", storef,0, + + [0x34] "stc", loadc, 0, /* page 99 */ + [0x37] "stdc", loadc, 0, + [0x35] "stcsr", loadcsr,0, + [0x36] "stdcq", loadcsr,0, + + [0x0D] "ldstub", store, 0, /* page 101 */ + [0x1D] "ldstuba", storea, 0, + + [0x0F] "swap", load, 0, /* page 102 */ + [0x1F] "swapa", loada, 0, }; +#pragma varargck argpos bprint 2 +#pragma varargck type "T" char* + +/* convert to lower case from upper, according to dascase */ +static int +Tfmt(Fmt *f) +{ + char buf[128]; + char *s, *t, *oa; + + oa = va_arg(f->args, char*); + if(dascase){ + for(s=oa,t=buf; *t = *s; s++,t++) + if('A'<=*t && *t<='Z') + *t += 'a'-'A'; + return fmtstrcpy(f, buf); + } + return fmtstrcpy(f, oa); +} + static void bprint(Instr *i, char *fmt, ...) { @@ -295,9 +307,9 @@ bprint(Instr *i, char *fmt, ...) } static int -decode(ulong pc, Instr *i) +decode(uvlong pc, Instr *i) { - long w; + ulong w; if (get4(mymap, pc, &w) < 0) { werrstr("can't read instruction: %r"); @@ -330,7 +342,7 @@ decode(ulong pc, Instr *i) } static int -mkinstr(ulong pc, Instr *i) +mkinstr(uvlong pc, Instr *i) { Instr xi; @@ -361,7 +373,7 @@ mkinstr(ulong pc, Instr *i) } static int -printins(Map *map, ulong pc, char *buf, int n) +printins(Map *map, uvlong pc, char *buf, int n) { Instr instr; void (*f)(Instr*, char*); @@ -382,7 +394,7 @@ printins(Map *map, ulong pc, char *buf, int n) break; case 1: - bprint(&instr, "%X", "CALL\t"); + bprint(&instr, "%T", "CALL\t"); instr.curr += symoff(instr.curr, instr.end-instr.curr, pc+instr.disp30*4, CTEXT); if (!dascase) @@ -413,32 +425,15 @@ printins(Map *map, ulong pc, char *buf, int n) return instr.size*4; } -/* convert to lower case from upper, according to dascase */ -static int -Xconv(Fmt *f) -{ - char buf[128]; - char *s, *t, *oa; - - oa = va_arg(f->args, char*); - if(dascase){ - for(s=oa,t=buf; *t = *s; s++,t++) - if('A'<=*t && *t<='Z') - *t += 'a'-'A'; - return fmtstrcpy(f, buf); - } - return fmtstrcpy(f, oa); -} - static int -sparcinst(Map *map, ulong pc, char modifier, char *buf, int n) +sparcinst(Map *map, uvlong pc, char modifier, char *buf, int n) { static int fmtinstalled = 0; /* a modifier of 'I' toggles the dissassembler type */ if (!fmtinstalled) { fmtinstalled = 1; - fmtinstall('X', Xconv); + fmtinstall('T', Tfmt); } if ((asstype == ASUNSPARC && modifier == 'i') || (asstype == ASPARC && modifier == 'I')) @@ -449,7 +444,7 @@ sparcinst(Map *map, ulong pc, char modifier, char *buf, int n) } static int -sparcdas(Map *map, ulong pc, char *buf, int n) +sparcdas(Map *map, uvlong pc, char *buf, int n) { Instr instr; @@ -470,7 +465,7 @@ sparcdas(Map *map, ulong pc, char *buf, int n) } static int -sparcinstlen(Map *map, ulong pc) +sparcinstlen(Map *map, uvlong pc) { Instr i; @@ -490,7 +485,7 @@ plocal(Instr *i) return -1; if (s.value > i->simm13) { if(getauto(&s, s.value-i->simm13, CAUTO, &s)) { - bprint(i, "%s+%d(SP)", s.name, s.value); + bprint(i, "%s+%lld(SP)", s.name, s.value); return 1; } } else { @@ -507,7 +502,7 @@ static void address(Instr *i) { Symbol s, s2; - long off, off1; + uvlong off, off1; if (i->rs1 == 1 && plocal(i) >= 0) return; @@ -517,7 +512,7 @@ address(Instr *i) && (s.class == CDATA || s.class == CTEXT)) { if(off==s.value && s.name[0]=='$'){ off1 = 0; - get4(mymap, s.value, &off1); + geta(mymap, s.value, &off1); if(off1 && findsym(off1, CANY, &s2) && s2.value == off1){ bprint(i, "$%s(SB)", s2.name); return; @@ -525,74 +520,74 @@ address(Instr *i) } bprint(i, "%s", s.name); if (s.value != off) - bprint(i, "+%lux", s.value-off); + bprint(i, "+%llux", s.value-off); bprint(i, "(SB)"); return; } - bprint(i, "%lux(R%d)", i->simm13, i->rs1); + bprint(i, "%ux(R%d)", i->simm13, i->rs1); } static void unimp(Instr *i, char *m) { - bprint(i, "%X", m); + bprint(i, "%T", m); } static char *bratab[16] = { /* page 91 */ - "N", /* 0x0 */ - "E", /* 0x1 */ - "LE", /* 0x2 */ - "L", /* 0x3 */ - "LEU", /* 0x4 */ - "CS", /* 0x5 */ - "NEG", /* 0x6 */ - "VS", /* 0x7 */ - "A", /* 0x8 */ - "NE", /* 0x9 */ - "G", /* 0xa */ - "GE", /* 0xb */ - "GU", /* 0xc */ - "CC", /* 0xd */ - "POS", /* 0xe */ - "VC", /* 0xf */ + [0X8] "A", + [0X0] "N", + [0X9] "NE", + [0X1] "E", + [0XA] "G", + [0X2] "LE", + [0XB] "GE", + [0X3] "L", + [0XC] "GU", + [0X4] "LEU", + [0XD] "CC", + [0X5] "CS", + [0XE] "POS", + [0X6] "NEG", + [0XF] "VC", + [0X7] "VS", }; static char *fbratab[16] = { /* page 91 */ - "N", /* 0x0 */ - "NE", /* 0x1 */ - "LG", /* 0x2 */ - "UL", /* 0x3 */ - "L", /* 0x4 */ - "UG", /* 0x5 */ - "G", /* 0x6 */ - "U", /* 0x7 */ - "A", /* 0x8 */ - "E", /* 0x9 */ - "UE", /* 0xa */ - "GE", /* 0xb */ - "UGE", /* 0xc */ - "LE", /* 0xd */ - "ULE", /* 0xe */ - "O", /* 0xf */ + [0X8] "A", + [0X0] "N", + [0X7] "U", + [0X6] "G", + [0X5] "UG", + [0X4] "L", + [0X3] "UL", + [0X2] "LG", + [0X1] "NE", + [0X9] "E", + [0XA] "UE", + [0XB] "GE", + [0XC] "UGE", + [0XD] "LE", + [0XE] "ULE", + [0XF] "O", }; static char *cbratab[16] = { /* page 91 */ - "N", /* 0x0 */ - "123", /* 0x1 */ - "12", /* 0x2 */ - "13", /* 0x3 */ - "1", /* 0x4 */ - "23", /* 0x5 */ - "2", /* 0x6 */ - "3", /* 0x7 */ - "A", /* 0x8 */ - "0", /* 0x9 */ - "03", /* 0xa */ - "02", /* 0xb */ - "023", /* 0xc */ - "01", /* 0xd */ - "013", /* 0xe */ - "012", /* 0xf */ + [0X8] "A", + [0X0] "N", + [0X7] "3", + [0X6] "2", + [0X5] "23", + [0X4] "1", + [0X3] "13", + [0X2] "12", + [0X1] "123", + [0X9] "0", + [0XA] "03", + [0XB] "02", + [0XC] "023", + [0XD] "01", + [0XE] "013", + [0XF] "012", }; static void @@ -602,9 +597,9 @@ bra1(Instr *i, char *m, char *tab[]) imm = i->simmdisp22; if(i->a) - bprint(i, "%X%X.%c\t", m, tab[i->cond], 'A'+dascase); + bprint(i, "%T%T.%c\t", m, tab[i->cond], 'A'+dascase); else - bprint(i, "%X%X\t", m, tab[i->cond]); + bprint(i, "%T%T\t", m, tab[i->cond]); i->curr += symoff(i->curr, i->end-i->curr, i->addr+4*imm, CTEXT); if (!dascase) bprint(i, "(SB)"); @@ -632,9 +627,9 @@ static void trap(Instr *i, char *m) /* page 101 */ { if(i->i == 0) - bprint(i, "%X%X\tR%d+R%d", m, bratab[i->cond], i->rs2, i->rs1); + bprint(i, "%T%T\tR%d+R%d", m, bratab[i->cond], i->rs2, i->rs1); else - bprint(i, "%X%X\t$%lux+R%d", m, bratab[i->cond], i->simm13, i->rs1); + bprint(i, "%T%T\t$%ux+R%d", m, bratab[i->cond], i->simm13, i->rs1); } static void @@ -644,7 +639,7 @@ sethi(Instr *i, char *m) /* page 89 */ imm = i->immdisp22<<10; if(dascase){ - bprint(i, "%X\t%lux, R%d", m, imm, i->rd); + bprint(i, "%T\t%lux, R%d", m, imm, i->rd); return; } if(imm==0 && i->rd==0){ @@ -740,25 +735,25 @@ shift(Instr *i, char *m) /* page 88 */ if(i->i == 0){ if(i->rs1 == i->rd) if(dascase) - bprint(i, "%X\tR%d, R%d", m, i->rs1, i->rs2); + bprint(i, "%T\tR%d, R%d", m, i->rs1, i->rs2); else - bprint(i, "%X\tR%d, R%d", m, i->rs2, i->rs1); + bprint(i, "%T\tR%d, R%d", m, i->rs2, i->rs1); else if(dascase) - bprint(i, "%X\tR%d, R%d, R%d", m, i->rs1, i->rs2, i->rd); + bprint(i, "%T\tR%d, R%d, R%d", m, i->rs1, i->rs2, i->rd); else - bprint(i, "%X\tR%d, R%d, R%d", m, i->rs2, i->rs1, i->rd); + bprint(i, "%T\tR%d, R%d, R%d", m, i->rs2, i->rs1, i->rd); }else{ if(i->rs1 == i->rd) if(dascase) - bprint(i, "%X\t$%d,R%d", m, i->simm13&0x1F, i->rs1); + bprint(i, "%T\t$%d,R%d", m, i->simm13&0x1F, i->rs1); else - bprint(i, "%X\tR%d, $%d", m, i->rs1, i->simm13&0x1F); + bprint(i, "%T\tR%d, $%d", m, i->rs1, i->simm13&0x1F); else if(dascase) - bprint(i, "%X\tR%d, $%d, R%d",m,i->rs1,i->simm13&0x1F,i->rd); + bprint(i, "%T\tR%d, $%d, R%d",m,i->rs1,i->simm13&0x1F,i->rd); else - bprint(i, "%X\t$%d, R%d, R%d",m,i->simm13&0x1F,i->rs1,i->rd); + bprint(i, "%T\t$%d, R%d, R%d",m,i->simm13&0x1F,i->rs1,i->rd); } } @@ -767,24 +762,24 @@ add(Instr *i, char *m) /* page 82 */ { if(i->i == 0){ if(dascase) - bprint(i, "%X\tR%d, R%d", m, i->rs1, i->rs2); + bprint(i, "%T\tR%d, R%d", m, i->rs1, i->rs2); else if(i->op3==2 && i->rs1==0 && i->rd) /* OR R2, R0, R1 */ bprint(i, "MOVW\tR%d", i->rs2); else - bprint(i, "%X\tR%d, R%d", m, i->rs2, i->rs1); + bprint(i, "%T\tR%d, R%d", m, i->rs2, i->rs1); }else{ if(dascase) - bprint(i, "%X\tR%d, $%lux", m, i->rs1, i->simm13); + bprint(i, "%T\tR%d, $%ux", m, i->rs1, i->simm13); else if(i->op3==0 && i->rd && i->rs1==0) /* ADD $x, R0, R1 */ - bprint(i, "MOVW\t$%lux", i->simm13); + bprint(i, "MOVW\t$%ux", i->simm13); else if(i->op3==0 && i->rd && i->rs1==2){ /* ADD $x, R2, R1 -> MOVW $x(SB), R1 */ bprint(i, "MOVW\t$"); address(i); } else - bprint(i, "%X\t$%lux, R%d", m, i->simm13, i->rs1); + bprint(i, "%T\t$%ux, R%d", m, i->simm13, i->rs1); } if(i->rs1 != i->rd) bprint(i, ", R%d", i->rd); @@ -800,7 +795,7 @@ cmp(Instr *i, char *m) if(i->i == 0) bprint(i, "CMP\tR%d, R%d", i->rs1, i->rs2); else - bprint(i, "CMP\tR%d, $%lux", i->rs1, i->simm13); + bprint(i, "CMP\tR%d, $%ux", i->rs1, i->simm13); } static char *regtab[4] = { @@ -817,14 +812,14 @@ wr(Instr *i, char *m) /* page 82 */ if(i->i == 0) bprint(i, "%s\tR%d, R%d", m, i->rs1, i->rs2); else - bprint(i, "%s\tR%d, $%lux", m, i->rs1, i->simm13); + bprint(i, "%s\tR%d, $%ux", m, i->rs1, i->simm13); }else{ if(i->i && i->simm13==0) bprint(i, "MOVW\tR%d", i->rs1); else if(i->i == 0) bprint(i, "wr\tR%d, R%d", i->rs2, i->rs1); else - bprint(i, "wr\t$%lux, R%d", i->simm13, i->rs1); + bprint(i, "wr\t$%ux, R%d", i->simm13, i->rs1); } bprint(i, ", %s", regtab[i->op3&3]); } @@ -849,14 +844,14 @@ jmpl(Instr *i, char *m) /* page 82 */ { if(i->i == 0){ if(i->rd == 15) - bprint(i, "%X\t(R%d+R%d)", "CALL", i->rs2, i->rs1); + bprint(i, "%T\t(R%d+R%d)", "CALL", i->rs2, i->rs1); else - bprint(i, "%X\t(R%d+R%d), R%d", m, i->rs2, i->rs1, i->rd); + bprint(i, "%T\t(R%d+R%d), R%d", m, i->rs2, i->rs1, i->rd); }else{ if(!dascase && i->simm13==8 && i->rs1==15 && i->rd==0) bprint(i, "RETURN"); else{ - bprint(i, "%X\t", m); + bprint(i, "%T\t", m); address(i); bprint(i, ", R%d", i->rd); } @@ -885,8 +880,8 @@ loadf(Instr *i, char *m) /* page 70 */ bprint(i, ", R%d", i->rd); } -static -void storef(Instr *i, char *m) /* page 70 */ +static void +storef(Instr *i, char *m) /* page 70 */ { if(!dascase){ m = "FMOVD"; @@ -908,8 +903,8 @@ void storef(Instr *i, char *m) /* page 70 */ address(i); } -static -void loadc(Instr *i, char *m) /* page 72 */ +static void +loadc(Instr *i, char *m) /* page 72 */ { if(i->i == 0) bprint(i, "%s\t(R%d+R%d), C%d", m, i->rs1, i->rs2, i->rd); @@ -920,8 +915,8 @@ void loadc(Instr *i, char *m) /* page 72 */ } } -static -void loadcsr(Instr *i, char *m) /* page 72 */ +static void +loadcsr(Instr *i, char *m) /* page 72 */ { if(i->i == 0) bprint(i, "%s\t(R%d+R%d), CSR", m, i->rs1, i->rs2); @@ -1002,19 +997,19 @@ fpop(Instr *i, char *m) /* page 108-116 */ } for(j=0; fptab1[j].name; j++) if(fptab1[j].opf == i->opf){ - bprint(i, "%X\tF%d, F%d", fptab1[j].name, i->rs2, i->rd); + bprint(i, "%T\tF%d, F%d", fptab1[j].name, i->rs2, i->rd); return; } for(j=0; fptab2[j].name; j++) if(fptab2[j].opf == i->opf){ - bprint(i, "%X\tF%d, F%d, F%d", fptab2[j].name, i->rs1, i->rs2, i->rd); + bprint(i, "%T\tF%d, F%d, F%d", fptab2[j].name, i->rs1, i->rs2, i->rd); return; } - bprint(i, "%X%ux\tF%d, F%d, F%d", m, i->opf, i->rs1, i->rs2, i->rd); + bprint(i, "%T%ux\tF%d, F%d, F%d", m, i->opf, i->rs1, i->rs2, i->rd); } static int -sparcfoll(Map *map, ulong pc, Rgetter rget, ulong *foll) +sparcfoll(Map *map, uvlong pc, Rgetter rget, uvlong *foll) { ulong w, r1, r2; char buf[8]; diff --git a/utils/libmach/machdata.c b/utils/libmach/machdata.c index a82e14e8..425173e6 100644 --- a/utils/libmach/machdata.c +++ b/utils/libmach/machdata.c @@ -16,11 +16,10 @@ int asstype = AMIPS; /* disassembler type */ Machdata *machdata; /* machine-dependent functions */ int -localaddr(Map *map, char *fn, char *var, long *r, Rgetter rget) +localaddr(Map *map, char *fn, char *var, uvlong *r, Rgetter rget) { Symbol s; - ulong fp; - ulong pc, sp, link; + uvlong fp, pc, sp, link; if (!lookup(fn, 0, &s)) { werrstr("function not found"); @@ -63,10 +62,10 @@ localaddr(Map *map, char *fn, char *var, long *r, Rgetter rget) } /* - * Print value v as name[+offset] and then the string s. + * Print value v as s.name[+offset] if possible, or just v. */ int -symoff(char *buf, int n, long v, int space) +symoff(char *buf, int n, uvlong v, int space) { Symbol s; int r; @@ -81,16 +80,17 @@ symoff(char *buf, int n, long v, int space) delta = -delta; } if (v == 0 || r == 0) - return snprint(buf, n, "%lux", v); + return snprint(buf, n, "%llux", v); if (s.type != 't' && s.type != 'T' && delta >= 4096) - return snprint(buf, n, "%lux", v); - if (strcmp(s.name, ".string") == 0) - return snprint(buf, n, "%lux", v); - if (delta) - return snprint(buf, n, "%s+%lux", s.name, v-s.value); + return snprint(buf, n, "%llux", v); + else if (strcmp(s.name, ".string") == 0) + return snprint(buf, n, "%llux", v); + else if (delta) + return snprint(buf, n, "%s+%lux", s.name, delta); else return snprint(buf, n, "%s", s.name); } + /* * Format floating point registers * @@ -105,7 +105,7 @@ int fpformat(Map *map, Reglist *rp, char *buf, int n, int modif) { char reg[12]; - long r; + ulong r; switch(rp->rformat) { @@ -116,10 +116,12 @@ fpformat(Map *map, Reglist *rp, char *buf, int n, int modif) break; case 'F': /* first reg of double reg pair */ if (modif == 'F') - if (((rp+1)->rflags&RFLT) && (rp+1)->rformat == 'f') { + if ((rp->rformat=='F') || (((rp+1)->rflags&RFLT) && (rp+1)->rformat == 'f')) { if (get1(map, rp->roffs, (uchar *)reg, 8) < 0) return -1; machdata->dftos(buf, n, reg); + if (rp->rformat == 'F') + return 1; return 2; } /* treat it like 'f' */ @@ -316,7 +318,6 @@ beieee80ftos(char *buf, int n, void *s) return beieeedftos(buf, n, (void*)ieee); } - int leieee80ftos(char *buf, int n, void *s) { @@ -331,19 +332,18 @@ leieee80ftos(char *buf, int n, void *s) } int -cisctrace(Map *map, ulong pc, ulong sp, ulong link, Tracer trace) +cisctrace(Map *map, uvlong pc, uvlong sp, uvlong link, Tracer trace) { Symbol s; - int found; - ulong opc; - long moved, j; + int found, i; + uvlong opc, moved; USED(link); - j = 0; + i = 0; opc = 0; while(pc && opc != pc) { moved = pc2sp(pc); - if (moved == -1) + if (moved == ~0) break; found = findsym(pc, CTEXT, &s); if (!found) @@ -353,22 +353,22 @@ cisctrace(Map *map, ulong pc, ulong sp, ulong link, Tracer trace) sp += moved; opc = pc; - if (get4(map, sp, (long *)&pc) < 0) + if (geta(map, sp, &pc) < 0) break; (*trace)(map, pc, sp, &s); sp += mach->szaddr; /*assumes address size = stack width*/ - if(++j > 40) + if(++i > 40) break; } - return j; + return i; } int -risctrace(Map *map, ulong pc, ulong sp, ulong link, Tracer trace) +risctrace(Map *map, uvlong pc, uvlong sp, uvlong link, Tracer trace) { int i; Symbol s, f; - ulong oldpc; + uvlong oldpc; i = 0; while(findsym(pc, CTEXT, &s)) { @@ -384,7 +384,7 @@ risctrace(Map *map, ulong pc, ulong sp, ulong link, Tracer trace) if(s.type == 'L' || s.type == 'l' || pc <= s.value+mach->pcquant) pc = link; else - if (get4(map, sp, (long *) &pc) < 0) + if (geta(map, sp, &pc) < 0) break; if(pc == 0 || (pc == oldpc && f.value == 0)) @@ -399,30 +399,30 @@ risctrace(Map *map, ulong pc, ulong sp, ulong link, Tracer trace) return i; } -ulong -ciscframe(Map *map, ulong addr, ulong pc, ulong sp, ulong link) +uvlong +ciscframe(Map *map, uvlong addr, uvlong pc, uvlong sp, uvlong link) { Symbol s; - int moved; + uvlong moved; USED(link); for(;;) { moved = pc2sp(pc); - if (moved == -1) + if (moved == ~0) break; sp += moved; findsym(pc, CTEXT, &s); if (addr == s.value) return sp; - if (get4(map, sp, (long *) &pc) < 0) + if (geta(map, sp, &pc) < 0) break; sp += mach->szaddr; /*assumes sizeof(addr) = stack width*/ } return 0; } -ulong -riscframe(Map *map, ulong addr, ulong pc, ulong sp, ulong link) +uvlong +riscframe(Map *map, uvlong addr, uvlong pc, uvlong sp, uvlong link) { Symbol s, f; @@ -443,7 +443,7 @@ riscframe(Map *map, ulong addr, ulong pc, ulong sp, ulong link) if (s.type == 'L' || s.type == 'l' || pc-s.value <= mach->szaddr*2) pc = link; else - if (get4(map, sp-f.value, (long *)&pc) < 0) + if (geta(map, sp-f.value, &pc) < 0) break; } return 0; diff --git a/utils/libmach/map.c b/utils/libmach/map.c index afb19b11..e1d6010e 100644 --- a/utils/libmach/map.c +++ b/utils/libmach/map.c @@ -25,7 +25,7 @@ newmap(Map *map, int n) } int -setmap(Map *map, int fd, ulong b, ulong e, ulong f, char *name) +setmap(Map *map, int fd, uvlong b, uvlong e, vlong f, char *name) { int i; @@ -45,7 +45,7 @@ setmap(Map *map, int fd, ulong b, ulong e, ulong f, char *name) return 1; } -static ulong +static uvlong stacktop(int pid) { char buf[64]; @@ -53,7 +53,7 @@ stacktop(int pid) int n; char *cp; - sprint(buf, "/proc/%d/segment", pid); + snprint(buf, sizeof(buf), "/proc/%d/segment", pid); fd = open(buf, 0); if (fd < 0) return 0; @@ -73,7 +73,7 @@ stacktop(int pid) cp++; if (!*cp) return 0; - return strtoul(cp, 0, 16); + return strtoull(cp, 0, 16); } Map* @@ -82,7 +82,7 @@ attachproc(int pid, int kflag, int corefd, Fhdr *fp) char buf[64], *regs; int fd; Map *map; - ulong n; + uvlong n; int mode; map = newmap(0, 4); @@ -115,13 +115,13 @@ attachproc(int pid, int kflag, int corefd, Fhdr *fp) setmap(map, fd, mach->regsize, mach->regsize+mach->fpregsize, 0, "fpregs"); } setmap(map, corefd, fp->txtaddr, fp->txtaddr+fp->txtsz, fp->txtaddr, "text"); - if(kflag || (ulong) fp->dataddr >= 0x7fffffff) { - setmap(map, corefd, fp->dataddr, 0xffffffff, fp->dataddr, "data"); + if(kflag || fp->dataddr >= mach->utop) { + setmap(map, corefd, fp->dataddr, ~0, fp->dataddr, "data"); return map; } n = stacktop(pid); if (n == 0) { - setmap(map, corefd, fp->dataddr, 0x7fffffff, fp->dataddr, "data"); + setmap(map, corefd, fp->dataddr, mach->utop, fp->dataddr, "data"); return map; } setmap(map, corefd, fp->dataddr, n, fp->dataddr, "data"); @@ -149,6 +149,28 @@ unusemap(Map *map, int i) } Map* +loadmap(Map *map, int fd, Fhdr *fp) +{ + map = newmap(map, 2); + if (map == 0) + return 0; + + map->seg[0].b = fp->txtaddr; + map->seg[0].e = fp->txtaddr+fp->txtsz; + map->seg[0].f = fp->txtoff; + map->seg[0].fd = fd; + map->seg[0].inuse = 1; + map->seg[0].name = "text"; + map->seg[1].b = fp->dataddr; + map->seg[1].e = fp->dataddr+fp->datsz; + map->seg[1].f = fp->datoff; + map->seg[1].fd = fd; + map->seg[1].inuse = 1; + map->seg[1].name = "data"; + return map; +} + +Map* attachremt(int fd, Fhdr *f) { Map *m; @@ -171,28 +193,6 @@ attachremt(int fd, Fhdr *f) return m; } -Map* -loadmap(Map *map, int fd, Fhdr *fp) -{ - map = newmap(map, 2); - if (map == 0) - return 0; - - map->seg[0].b = fp->txtaddr; - map->seg[0].e = fp->txtaddr+fp->txtsz; - map->seg[0].f = fp->txtoff; - map->seg[0].fd = fd; - map->seg[0].inuse = 1; - map->seg[0].name = "text"; - map->seg[1].b = fp->dataddr; - map->seg[1].e = fp->dataddr+fp->datsz; - map->seg[1].f = fp->datoff; - map->seg[1].fd = fd; - map->seg[1].inuse = 1; - map->seg[1].name = "data"; - return map; -} - void setmapio(Map *map, int i, Rsegio get, Rsegio put) { diff --git a/utils/libmach/mkfile b/utils/libmach/mkfile index 1f0a2950..a5e87357 100644 --- a/utils/libmach/mkfile +++ b/utils/libmach/mkfile @@ -7,12 +7,12 @@ OFILES=\ 5.$O\ 6.$O\ 8.$O\ + 9.$O\ k.$O\ q.$O\ t.$O\ v.$O\ 2db.$O\ - 4db.$O\ 5db.$O\ 8db.$O\ kdb.$O\ @@ -23,6 +23,7 @@ OFILES=\ 5obj.$O\ 6obj.$O\ 8obj.$O\ + 9obj.$O\ kobj.$O\ qobj.$O\ vobj.$O\ @@ -36,10 +37,10 @@ OFILES=\ executable.$O\ vcodas.$O\ -HFILES=mach.h a.out.h bootexec.h elf.h ureg2.h ureg4.h ureg6.h ureg8.h uregk.h uregv.h ureg5.h +HFILES=../include/mach.h ../include/a.out.h bootexec.h elf.h ureg2.h ureg4.h ureg6.h ureg8.h uregk.h uregv.h ureg5.h <$ROOT/mkfiles/mksyslib-$SHELLTYPE -CFLAGS= $CFLAGS -I.. +CFLAGS= $CFLAGS -I../include -I.. package:QV: $TRUE diff --git a/utils/libmach/obj.c b/utils/libmach/obj.c index 39f2fad4..812369ba 100644 --- a/utils/libmach/obj.c +++ b/utils/libmach/obj.c @@ -4,7 +4,7 @@ */ #include <lib9.h> #include <bio.h> -#include "ar.h" +#include <ar.h> #include "mach.h" #include "obj.h" @@ -22,23 +22,21 @@ enum int _is2(char*), /* in [$OS].c */ _is5(char*), _is6(char*), + _is7(char*), _is8(char*), _is9(char*), _isk(char*), _isq(char*), - _ist(char*), _isv(char*), - _isx(char*), _read2(Biobuf*, Prog*), _read5(Biobuf*, Prog*), _read6(Biobuf*, Prog*), + _read7(Biobuf*, Prog*), _read8(Biobuf*, Prog*), _read9(Biobuf*, Prog*), _readk(Biobuf*, Prog*), _readq(Biobuf*, Prog*), - _readt(Biobuf*, Prog*), - _readv(Biobuf*, Prog*), - _readx(Biobuf*, Prog*); + _readv(Biobuf*, Prog*); typedef struct Obj Obj; typedef struct Symtab Symtab; @@ -52,18 +50,15 @@ struct Obj /* functions to handle each intermediate (.$O) file */ static Obj obj[] = { /* functions to identify and parse each type of obj */ - /*[Obj68020]*/ "68020 .2", _is2, _read2, - /*[ObjSparc]*/ "sparc .k", _isk, _readk, - /*[ObjMips]*/ "mips .v", _isv, _readv, - /*[Obj386]*/ "386 .8", _is8, _read8, - /*[Obj960]*/ "960 .6", 0, 0, - /*[Obj3210]*/ "3210 .x", 0, 0, - /*[ObjMips2]*/ "mips2 .4", 0, 0, - /*[Obj29000]*/ "29000 .9", 0, 0, - /*[ObjArm]*/ "arm .5", _is5, _read5, - /*[ObjPower]*/ "power .q", _isq, _readq, - /*[ObjMips2le]*/ "mips2 .0", 0, 0, - /*[Maxobjtype]*/ 0, 0 + [Obj68020] "68020 .2", _is2, _read2, + [ObjAmd64] "amd64 .6", _is6, _read6, + [ObjArm] "arm .5", _is5, _read5, + [Obj386] "386 .8", _is8, _read8, + [ObjSparc] "sparc .k", _isk, _readk, + [ObjPower] "power .q", _isq, _readq, + [ObjMips] "mips .v", _isv, _readv, + [ObjPower64] "power64 .9", _is9, _read9, + [Maxobjtype] 0, 0 }; struct Symtab @@ -77,7 +72,7 @@ static Sym *names[NNAMES]; /* working set of active names */ static int processprog(Prog*,int); /* decode each symbol reference */ static void objreset(void); -static void objlookup(int, char *, int ); +static void objlookup(int, char *, int, uint); static void objupdate(int, int); int @@ -130,14 +125,14 @@ readobj(Biobuf *bp, int objtype) } int -readar(Biobuf *bp, int objtype, int end, int doautos) +readar(Biobuf *bp, int objtype, vlong end, int doautos) { Prog p; if (objtype < 0 || objtype >= Maxobjtype || obj[objtype].is == 0) return 1; objreset(); - while ((*obj[objtype].read)(bp, &p) && BOFFSET(bp) < end) + while ((*obj[objtype].read)(bp, &p) && Boffset(bp) < end) if (!processprog(&p, doautos)) return 0; return 1; @@ -159,7 +154,7 @@ processprog(Prog *p, int doautos) if (!doautos) if(p->type != 'U' && p->type != 'b') break; - objlookup(p->sym, p->id, p->type); + objlookup(p->sym, p->id, p->type, p->sig); break; case aText: objupdate(p->sym, 'T'); @@ -178,7 +173,7 @@ processprog(Prog *p, int doautos) * make a new entry if it is not already there. */ static void -objlookup(int id, char *name, int type) +objlookup(int id, char *name, int type, uint sig) { long h; char *cp; @@ -188,6 +183,7 @@ objlookup(int id, char *name, int type) s = names[id]; if(s && strcmp(s->name, name) == 0) { s->type = type; + s->sig = sig; return; } @@ -232,6 +228,7 @@ objlookup(int id, char *name, int type) sp = malloc(sizeof(Symtab)); sp->s.name = name; sp->s.type = type; + sp->s.sig = sig; sp->s.value = islocal(type) ? MAXOFF : 0; names[id] = &sp->s; sp->next = hash[h]; @@ -256,7 +253,7 @@ objtraverse(void (*fn)(Sym*, void*), void *pointer) * update the offset information for a 'a' or 'p' symbol in an intermediate file */ void -_offset(int id, long off) +_offset(int id, vlong off) { Sym *s; @@ -302,7 +299,7 @@ nextar(Biobuf *bp, int offset, char *buf) for(i=0; i<sizeof(a.name) && i<SARNAME && a.name[i] != ' '; i++) buf[i] = a.name[i]; buf[i] = 0; - arsize = atol(a.size); + arsize = strtol(a.size, 0, 0); if (arsize&1) arsize++; return arsize + SAR_HDR; diff --git a/utils/libmach/obj.h b/utils/libmach/obj.h index 2d2dfea6..d8c507aa 100644 --- a/utils/libmach/obj.h +++ b/utils/libmach/obj.h @@ -18,7 +18,8 @@ struct Prog /* info from .$O files */ char type; /* type of the symbol: ie, 'T', 'a', etc. */ char sym; /* index of symbol's name */ char *id; /* name for the symbol, if it introduces one */ + uint sig; /* type signature for symbol */ }; #define UNKNOWN '?' -void _offset(int, long); +void _offset(int, vlong); diff --git a/utils/libmach/q.c b/utils/libmach/q.c index 858882bf..f73ade9f 100644 --- a/utils/libmach/q.c +++ b/utils/libmach/q.c @@ -2,7 +2,7 @@ * PowerPC definition * forsyth@terzarima.net */ -#include <lib9.h> +#include <u.h> #include <bio.h> #include "uregq.h" #include "mach.h" @@ -17,84 +17,84 @@ #define R31 REGOFF(r31) #define FP_REG(x) (R31+4+8*(x)) -#define REGSIZE sizeof(struct Ureg) -#define FPREGSIZE (8*33) +#define REGSIZE sizeof(struct Ureg) +#define FPREGSIZE (8*33) Reglist powerreglist[] = { - {"CAUSE", REGOFF(cause), RINT|RRDONLY, 'X'}, - {"SRR1", REGOFF(status), RINT|RRDONLY, 'X'}, - {"PC", REGOFF(pc), RINT, 'X'}, - {"LR", REGOFF(lr), RINT, 'X'}, - {"CR", REGOFF(cr), RINT, 'X'}, - {"XER", REGOFF(xer), RINT, 'X'}, - {"CTR", REGOFF(ctr), RINT, 'X'}, - {"PC", PC, RINT, 'X'}, - {"SP", SP, RINT, 'X'}, - {"R0", REGOFF(r0), RINT, 'X'}, + {"CAUSE", REGOFF(cause), RINT|RRDONLY, 'X'}, + {"SRR1", REGOFF(srr1), RINT|RRDONLY, 'X'}, + {"PC", REGOFF(pc), RINT, 'X'}, + {"LR", REGOFF(lr), RINT, 'X'}, + {"CR", REGOFF(cr), RINT, 'X'}, + {"XER", REGOFF(xer), RINT, 'X'}, + {"CTR", REGOFF(ctr), RINT, 'X'}, + {"PC", PC, RINT, 'X'}, + {"SP", SP, RINT, 'X'}, + {"R0", REGOFF(r0), RINT, 'X'}, /* R1 is SP */ - {"R2", REGOFF(r2), RINT, 'X'}, - {"R3", REGOFF(r3), RINT, 'X'}, - {"R4", REGOFF(r4), RINT, 'X'}, - {"R5", REGOFF(r5), RINT, 'X'}, - {"R6", REGOFF(r6), RINT, 'X'}, - {"R7", REGOFF(r7), RINT, 'X'}, - {"R8", REGOFF(r8), RINT, 'X'}, - {"R9", REGOFF(r9), RINT, 'X'}, - {"R10", REGOFF(r10), RINT, 'X'}, - {"R11", REGOFF(r11), RINT, 'X'}, - {"R12", REGOFF(r12), RINT, 'X'}, - {"R13", REGOFF(r13), RINT, 'X'}, - {"R14", REGOFF(r14), RINT, 'X'}, - {"R15", REGOFF(r15), RINT, 'X'}, - {"R16", REGOFF(r16), RINT, 'X'}, - {"R17", REGOFF(r17), RINT, 'X'}, - {"R18", REGOFF(r18), RINT, 'X'}, - {"R19", REGOFF(r19), RINT, 'X'}, - {"R20", REGOFF(r20), RINT, 'X'}, - {"R21", REGOFF(r21), RINT, 'X'}, - {"R22", REGOFF(r22), RINT, 'X'}, - {"R23", REGOFF(r23), RINT, 'X'}, - {"R24", REGOFF(r24), RINT, 'X'}, - {"R25", REGOFF(r25), RINT, 'X'}, - {"R26", REGOFF(r26), RINT, 'X'}, - {"R27", REGOFF(r27), RINT, 'X'}, - {"R28", REGOFF(r28), RINT, 'X'}, - {"R29", REGOFF(r29), RINT, 'X'}, - {"R30", REGOFF(r30), RINT, 'X'}, - {"R31", REGOFF(r31), RINT, 'X'}, - {"F0", FP_REG(0), RFLT, 'D'}, - {"F1", FP_REG(1), RFLT, 'D'}, - {"F2", FP_REG(2), RFLT, 'D'}, - {"F3", FP_REG(3), RFLT, 'D'}, - {"F4", FP_REG(4), RFLT, 'D'}, - {"F5", FP_REG(5), RFLT, 'D'}, - {"F6", FP_REG(6), RFLT, 'D'}, - {"F7", FP_REG(7), RFLT, 'D'}, - {"F8", FP_REG(8), RFLT, 'D'}, - {"F9", FP_REG(9), RFLT, 'D'}, - {"F10", FP_REG(10), RFLT, 'D'}, - {"F11", FP_REG(11), RFLT, 'D'}, - {"F12", FP_REG(12), RFLT, 'D'}, - {"F13", FP_REG(13), RFLT, 'D'}, - {"F14", FP_REG(14), RFLT, 'D'}, - {"F15", FP_REG(15), RFLT, 'D'}, - {"F16", FP_REG(16), RFLT, 'D'}, - {"F17", FP_REG(17), RFLT, 'D'}, - {"F18", FP_REG(18), RFLT, 'D'}, - {"F19", FP_REG(19), RFLT, 'D'}, - {"F20", FP_REG(20), RFLT, 'D'}, - {"F21", FP_REG(21), RFLT, 'D'}, - {"F22", FP_REG(22), RFLT, 'D'}, - {"F23", FP_REG(23), RFLT, 'D'}, - {"F24", FP_REG(24), RFLT, 'D'}, - {"F25", FP_REG(25), RFLT, 'D'}, - {"F26", FP_REG(26), RFLT, 'D'}, - {"F27", FP_REG(27), RFLT, 'D'}, - {"F28", FP_REG(28), RFLT, 'D'}, - {"F29", FP_REG(29), RFLT, 'D'}, - {"F30", FP_REG(30), RFLT, 'D'}, - {"F31", FP_REG(31), RFLT, 'D'}, - {"FPSCR", FP_REG(32)+4, RFLT, 'X'}, + {"R2", REGOFF(r2), RINT, 'X'}, + {"R3", REGOFF(r3), RINT, 'X'}, + {"R4", REGOFF(r4), RINT, 'X'}, + {"R5", REGOFF(r5), RINT, 'X'}, + {"R6", REGOFF(r6), RINT, 'X'}, + {"R7", REGOFF(r7), RINT, 'X'}, + {"R8", REGOFF(r8), RINT, 'X'}, + {"R9", REGOFF(r9), RINT, 'X'}, + {"R10", REGOFF(r10), RINT, 'X'}, + {"R11", REGOFF(r11), RINT, 'X'}, + {"R12", REGOFF(r12), RINT, 'X'}, + {"R13", REGOFF(r13), RINT, 'X'}, + {"R14", REGOFF(r14), RINT, 'X'}, + {"R15", REGOFF(r15), RINT, 'X'}, + {"R16", REGOFF(r16), RINT, 'X'}, + {"R17", REGOFF(r17), RINT, 'X'}, + {"R18", REGOFF(r18), RINT, 'X'}, + {"R19", REGOFF(r19), RINT, 'X'}, + {"R20", REGOFF(r20), RINT, 'X'}, + {"R21", REGOFF(r21), RINT, 'X'}, + {"R22", REGOFF(r22), RINT, 'X'}, + {"R23", REGOFF(r23), RINT, 'X'}, + {"R24", REGOFF(r24), RINT, 'X'}, + {"R25", REGOFF(r25), RINT, 'X'}, + {"R26", REGOFF(r26), RINT, 'X'}, + {"R27", REGOFF(r27), RINT, 'X'}, + {"R28", REGOFF(r28), RINT, 'X'}, + {"R29", REGOFF(r29), RINT, 'X'}, + {"R30", REGOFF(r30), RINT, 'X'}, + {"R31", REGOFF(r31), RINT, 'X'}, + {"F0", FP_REG(0), RFLT, 'F'}, + {"F1", FP_REG(1), RFLT, 'F'}, + {"F2", FP_REG(2), RFLT, 'F'}, + {"F3", FP_REG(3), RFLT, 'F'}, + {"F4", FP_REG(4), RFLT, 'F'}, + {"F5", FP_REG(5), RFLT, 'F'}, + {"F6", FP_REG(6), RFLT, 'F'}, + {"F7", FP_REG(7), RFLT, 'F'}, + {"F8", FP_REG(8), RFLT, 'F'}, + {"F9", FP_REG(9), RFLT, 'F'}, + {"F10", FP_REG(10), RFLT, 'F'}, + {"F11", FP_REG(11), RFLT, 'F'}, + {"F12", FP_REG(12), RFLT, 'F'}, + {"F13", FP_REG(13), RFLT, 'F'}, + {"F14", FP_REG(14), RFLT, 'F'}, + {"F15", FP_REG(15), RFLT, 'F'}, + {"F16", FP_REG(16), RFLT, 'F'}, + {"F17", FP_REG(17), RFLT, 'F'}, + {"F18", FP_REG(18), RFLT, 'F'}, + {"F19", FP_REG(19), RFLT, 'F'}, + {"F20", FP_REG(20), RFLT, 'F'}, + {"F21", FP_REG(21), RFLT, 'F'}, + {"F22", FP_REG(22), RFLT, 'F'}, + {"F23", FP_REG(23), RFLT, 'F'}, + {"F24", FP_REG(24), RFLT, 'F'}, + {"F25", FP_REG(25), RFLT, 'F'}, + {"F26", FP_REG(26), RFLT, 'F'}, + {"F27", FP_REG(27), RFLT, 'F'}, + {"F28", FP_REG(28), RFLT, 'F'}, + {"F29", FP_REG(29), RFLT, 'F'}, + {"F30", FP_REG(30), RFLT, 'F'}, + {"F31", FP_REG(31), RFLT, 'F'}, + {"FPSCR", FP_REG(32)+4, RFLT, 'X'}, { 0 } }; @@ -104,16 +104,17 @@ Mach mpower = "power", MPOWER, /* machine type */ powerreglist, /* register set */ - REGSIZE, /* register set size in bytes */ - FPREGSIZE, /* floating point register size in bytes */ + REGSIZE, /* number of bytes in register set */ + FPREGSIZE, /* number of bytes in FP register set */ "PC", /* name of PC */ "SP", /* name of SP */ "LR", /* name of link register */ "setSB", /* static base register name */ 0, /* value */ 0x1000, /* page size */ - 0x20000000, /* kernel base */ - 0, /* kernel text mask */ + 0x80000000ULL, /* kernel base */ + 0xF0000000ULL, /* kernel text mask */ + 0x7FFFFFFFULL, /* user stack top */ 4, /* quantization of pc */ 4, /* szaddr */ 4, /* szreg */ diff --git a/utils/libmach/qdb.c b/utils/libmach/qdb.c index 890408b1..36bc3436 100644 --- a/utils/libmach/qdb.c +++ b/utils/libmach/qdb.c @@ -3,15 +3,16 @@ #include "mach.h" /* - * PowerPC-specific debugger interface + * PowerPC-specific debugger interface, + * including 64-bit modes * forsyth@terzarima.net */ static char *powerexcep(Map*, Rgetter); -static int powerfoll(Map*, ulong, Rgetter, ulong*); -static int powerinst(Map*, ulong, char, char*, int); -static int powerinstlen(Map*, ulong); -static int powerdas(Map*, ulong, char*, int); +static int powerfoll(Map*, uvlong, Rgetter, uvlong*); +static int powerinst(Map*, uvlong, char, char*, int); +static int powerinstlen(Map*, uvlong); +static int powerdas(Map*, uvlong, char*, int); /* * Machine description @@ -21,8 +22,8 @@ Machdata powermach = {0x07f, 0xe0, 0x00, 0x08}, /* breakpoint (tw 31,r0,r0) */ 4, /* break point size */ - beswab, /* convert short to local byte order */ - beswal, /* convert long to local byte order */ + beswab, /* short to local byte order */ + beswal, /* long to local byte order */ beswav, /* vlong to local byte order */ risctrace, /* print C traceback */ riscframe, /* frame finder */ @@ -66,11 +67,11 @@ static char *excname[] = "reserved 19", "reserved 1A", /* the following are made up on a program exception */ - "floating point exception", /* 1B: FPEXC */ - "illegal instruction", /* 1C */ - "privileged instruction", /* 1D */ - "trap", /* 1E */ - "illegal operation", /* 1F */ + "floating point exception", /* FPEXC */ + "illegal instruction", + "privileged instruction", + "trap", + "illegal operation", "breakpoint", /* 20 */ }; @@ -112,11 +113,11 @@ typedef struct { uchar bi; /* bits 11-15 */ uchar bo; /* bits 6-10 */ uchar crbd; /* bits 6-10 */ - /*union {*/ + /* union { */ short d; /* bits 16-31 */ short simm; ushort uimm; - /*};*/ + /*}; */ uchar fm; /* bits 7-14 */ uchar fra; /* bits 11-15 */ uchar frb; /* bits 16-20 */ @@ -128,13 +129,15 @@ typedef struct { uchar lk; /* bit 31 */ uchar mb; /* bits 21-25 */ uchar me; /* bits 26-30 */ + uchar xmbe; /* bits 26,21-25: mb[5] || mb[0:4], also xme */ + uchar xsh; /* bits 30,16-20: sh[5] || sh[0:4] */ uchar nb; /* bits 16-20 */ uchar op; /* bits 0-5 */ uchar oe; /* bit 21 */ uchar ra; /* bits 11-15 */ uchar rb; /* bits 16-20 */ uchar rc; /* bit 31 */ - /* union {*/ + /* union { */ uchar rs; /* bits 6-10 */ uchar rd; /*};*/ @@ -143,11 +146,12 @@ typedef struct { uchar to; /* bits 6-10 */ uchar imm; /* bits 16-19 */ ushort xo; /* bits 21-30, 22-30, 26-30, or 30 (beware) */ - long immediate; + uvlong imm64; long w0; long w1; - ulong addr; /* pc of instruction */ + uvlong addr; /* pc of instruction */ short target; + short m64; /* 64-bit mode */ char *curr; /* current fill level in output buffer */ char *end; /* end of buffer */ int size; /* number of longs in instr */ @@ -157,6 +161,8 @@ typedef struct { #define IBF(v,a,b) (((ulong)(v)>>(32-(b)-1)) & ~(~0L<<(((b)-(a)+1)))) #define IB(v,b) IBF((v),(b),(b)) +#pragma varargck argpos bprint 2 + static void bprint(Instr *i, char *fmt, ...) { @@ -168,14 +174,15 @@ bprint(Instr *i, char *fmt, ...) } static int -decode(ulong pc, Instr *i) +decode(uvlong pc, Instr *i) { - long w; + ulong w; if (get4(mymap, pc, &w) < 0) { werrstr("can't read instruction: %r"); return -1; } + i->m64 = asstype == APOWER64; i->aa = IB(w, 30); i->crba = IBF(w, 11, 15); i->crbb = IBF(w, 16, 20); @@ -188,8 +195,6 @@ decode(ulong pc, Instr *i) i->bo = IBF(w, 6, 10); i->crbd = IBF(w, 6, 10); i->uimm = IBF(w, 16, 31); /* also d, simm */ - i->simm = i->uimm; - i->d = i->uimm; i->fm = IBF(w, 7, 14); i->fra = IBF(w, 11, 15); i->frb = IBF(w, 16, 20); @@ -203,6 +208,7 @@ decode(ulong pc, Instr *i) i->lk = IB(w, 31); i->mb = IBF(w, 21, 25); i->me = IBF(w, 26, 30); + i->xmbe = (IB(w,26)<<5) | i->mb; i->nb = IBF(w, 16, 20); i->op = IBF(w, 0, 5); i->oe = IB(w, 21); @@ -210,15 +216,21 @@ decode(ulong pc, Instr *i) i->rb = IBF(w, 16, 20); i->rc = IB(w, 31); i->rs = IBF(w, 6, 10); /* also rd */ - i->rd = i->rs; i->sh = IBF(w, 16, 20); + i->xsh = (IB(w, 30)<<5) | i->sh; i->spr = IBF(w, 11, 20); i->to = IBF(w, 6, 10); i->imm = IBF(w, 16, 19); i->xo = IBF(w, 21, 30); /* bits 21-30, 22-30, 26-30, or 30 (beware) */ - i->immediate = i->simm; + if(i->op == 58){ /* class of 64-bit loads */ + i->xo = i->simm & 3; + i->simm &= ~3; + } + i->imm64 = i->simm; if(i->op == 15) - i->immediate <<= 16; + i->imm64 <<= 16; + else if(i->op == 25 || i->op == 27 || i->op == 29) + i->imm64 = (uvlong)(i->uimm<<16); i->w0 = w; i->target = -1; i->addr = pc; @@ -227,7 +239,7 @@ decode(ulong pc, Instr *i) } static int -mkinstr(ulong pc, Instr *i) +mkinstr(uvlong pc, Instr *i) { Instr x; @@ -235,26 +247,15 @@ mkinstr(ulong pc, Instr *i) return -1; /* * combine ADDIS/ORI (CAU/ORIL) into MOVW + * also ORIS/ORIL for unsigned in 64-bit mode */ - if (i->op == 15 && i->ra==0) { + if ((i->op == 15 || i->op == 25) && i->ra==0) { if(decode(pc+4, &x) < 0) return -1; if (x.op == 24 && x.rs == x.ra && x.ra == i->rd) { - i->immediate |= (x.immediate & 0xFFFF); - i->w1 = x.w0; - i->target = x.rd; - i->size++; - return 1; - } - } - if (i->op == 15 && i->ra==REGSB && mach->sb) { - if(decode(pc+4, &x) < 0) - return -1; - if (x.op >= 32 && x.op < 54 && i->rd == x.ra) { - i->op = x.op; - i->ra = REGSB; - i->rs = i->rd = x.rd; - i->immediate += x.simm; + i->imm64 |= (x.imm64 & 0xFFFF); + if(i->op != 15) + i->imm64 &= 0xFFFFFFFFUL; i->w1 = x.w0; i->target = x.rd; i->size++; @@ -267,20 +268,20 @@ mkinstr(ulong pc, Instr *i) static int plocal(Instr *i) { - int offset; + long offset; Symbol s; if (!findsym(i->addr, CTEXT, &s) || !findlocal(&s, FRAMENAME, &s)) return -1; - offset = s.value - i->immediate; + offset = s.value - i->imm64; if (offset > 0) { if(getauto(&s, offset, CAUTO, &s)) { - bprint(i, "%s+%d(SP)", s.name, s.value); + bprint(i, "%s+%lld(SP)", s.name, s.value); return 1; } } else { if (getauto(&s, -offset-4, CPARAM, &s)) { - bprint(i, "%s+%d(FP)", s.name, -offset); + bprint(i, "%s+%ld(FP)", s.name, -offset); return 1; } } @@ -288,18 +289,17 @@ plocal(Instr *i) } static int -pglobal(Instr *i, long off, int anyoff, char *reg) +pglobal(Instr *i, uvlong off, int anyoff, char *reg) { Symbol s, s2; - long off1; + uvlong off1; if(findsym(off, CANY, &s) && - strcmp(s.name, ".string") != 0 && - (ulong)(off-s.value) < 4096 && + s.value-off < 4096 && (s.class == CDATA || s.class == CTEXT)) { if(off==s.value && s.name[0]=='$'){ off1 = 0; - get4(mymap, s.value, &off1); + geta(mymap, s.value, &off1); if(off1 && findsym(off1, CANY, &s2) && s2.value == off1){ bprint(i, "$%s%s", s2.name, reg); return 1; @@ -307,13 +307,13 @@ pglobal(Instr *i, long off, int anyoff, char *reg) } bprint(i, "%s", s.name); if (s.value != off) - bprint(i, "+%lux", off-s.value); + bprint(i, "+%llux", off-s.value); bprint(i, reg); return 1; } if(!anyoff) return 0; - bprint(i, "%lux%s", off, reg); + bprint(i, "%llux%s", off, reg); return 1; } @@ -322,16 +322,12 @@ address(Instr *i) { if (i->ra == REGSP && plocal(i) >= 0) return; - if (i->ra == REGSB && mach->sb && pglobal(i, mach->sb+i->immediate, 0, "(SB)") > 0) + if (i->ra == REGSB && mach->sb && pglobal(i, mach->sb+i->imm64, 0, "(SB)") >= 0) return; - if(i->immediate < 0) - bprint(i, "-%lx", -i->immediate); - else - bprint(i, "%lux", i->immediate); - if (i->ra == REGSB && mach->sb) - bprint(i, "(SB)"); + if(i->simm < 0) + bprint(i, "-%x(R%d)", -i->simm, i->ra); else - bprint(i, "(R%d)", i->ra); + bprint(i, "%llux(R%d)", i->imm64, i->ra); } static char *tcrbits[] = {"LT", "GT", "EQ", "VS"}; @@ -362,12 +358,12 @@ branch(Opcode *o, Instr *i) if(bo != 20) { bi = i->bi&3; sprint(buf, "B%s%%L", bo==12? tcrbits[bi]: fcrbits[bi]); - format(buf, i, 0); + format(buf, i, nil); bprint(i, "\t"); if(i->bi > 4) bprint(i, "CR(%d),", i->bi/4); } else - format("BR%L\t", i, 0); + format("BR%L\t", i, nil); if(i->op == 16) format(0, i, "%J"); else if(i->op == 19 && i->xo == 528) @@ -383,7 +379,7 @@ addi(Opcode *o, Instr *i) { if (i->op==14 && i->ra == 0) format("MOVW", i, "%i,R%d"); - else if (i->ra == REGSP || i->ra == REGSB) { + else if (i->ra == REGSB) { bprint(i, "MOVW\t$"); address(i); bprint(i, ",R%d", i->rd); @@ -403,23 +399,19 @@ addis(Opcode *o, Instr *i) { long v; - v = i->immediate; - if (i->op==15 && i->ra == 0) { - bprint(i, "MOVW\t$"); - pglobal(i, i->immediate, 1, ""); - bprint(i, ",R%d", i->rd); - } - else if (i->op==15 && i->ra == REGSB && mach->sb) { + v = i->imm64; + if (i->op==15 && i->ra == 0) + bprint(i, "MOVW\t$%lux,R%d", v, i->rd); + else if (i->op==15 && i->ra == REGSB) { bprint(i, "MOVW\t$"); address(i); bprint(i, ",R%d", i->rd); -/* how about auto/param addresses? */ } else if(i->op==15 && v < 0) { - bprint(i, "SUB\t$%d,R%d", -v, i->ra); + bprint(i, "SUB\t$%ld,R%d", -v, i->ra); if(i->rd != i->ra) bprint(i, ",R%d", i->rd); } else { - format(o->mnemonic, i, 0); + format(o->mnemonic, i, nil); bprint(i, "\t$%ld,R%d", v, i->ra); if(i->rd != i->ra) bprint(i, ",R%d", i->rd); @@ -509,7 +501,8 @@ dcb(Opcode *o, Instr *i) static void lw(Opcode *o, Instr *i, char r) { - bprint(i, "%s\t", o->mnemonic); + format(o->mnemonic, i, nil); + bprint(i, "\t"); address(i); bprint(i, ",%c%d", r, i->rd); } @@ -530,29 +523,28 @@ static void sw(Opcode *o, Instr *i, char r) { int offset; - char *m; Symbol s; - m = o->mnemonic; - if (i->ra == REGSP) { + if (i->rs == REGSP) { if (findsym(i->addr, CTEXT, &s) && findlocal(&s, FRAMENAME, &s)) { - offset = s.value-i->immediate; + offset = s.value-i->imm64; if (offset > 0 && getauto(&s, offset, CAUTO, &s)) { - bprint(i, "%s\t%c%d,%s-%d(SP)", m, r, i->rs, - s.name, offset); + format(o->mnemonic, i, nil); + bprint(i, "\t%c%d,%s-%d(SP)", r, i->rd, s.name, offset); return; } } } - if (i->ra == REGSP || i->ra == REGSB && mach->sb) { - bprint(i, "%s\t%c%d,", m, r, i->rs); + if (i->rs == REGSB && mach->sb) { + format(o->mnemonic, i, nil); + bprint(i, "\t%c%d,", r, i->rd); address(i); return; } if (r == 'F') - format(m, i, "F%d,%l"); + format(o->mnemonic, i, "F%d,%l"); else - format(m, i, o->ken); + format(o->mnemonic, i, o->ken); } static void @@ -599,7 +591,8 @@ add(Opcode *o, Instr *i) static void sub(Opcode *o, Instr *i) { - format(o->mnemonic, i, 0); + format(o->mnemonic, i, nil); + bprint(i, "\t"); if(i->op == 31) { bprint(i, "\tR%d,R%d", i->ra, i->rb); /* subtract Ra from Rb */ if(i->rd != i->rb) @@ -609,9 +602,9 @@ sub(Opcode *o, Instr *i) } static void -qmuldiv(Opcode *o, Instr *i) +qdiv(Opcode *o, Instr *i) { - format(o->mnemonic, i, 0); + format(o->mnemonic, i, nil); if(i->op == 31) bprint(i, "\tR%d,R%d", i->rb, i->ra); else @@ -646,7 +639,7 @@ or(Opcode *o, Instr *i) if (i->op == 31) { /* Rb,Rs,Ra */ if (i->rs == 0 && i->ra == 0 && i->rb == 0) - format("NOP", i, 0); + format("NOP", i, nil); else if (i->rs == i->rb) format("MOVW", i, "R%b,R%a"); else @@ -658,7 +651,7 @@ or(Opcode *o, Instr *i) static void shifted(Opcode *o, Instr *i) { - format(o->mnemonic, i, 0); + format(o->mnemonic, i, nil); bprint(i, "\t$%lux,", (ulong)i->uimm<<16); if (i->rs == i->ra) bprint(i, "R%d", i->ra); @@ -679,7 +672,7 @@ static char ir2[] = "R%a,R%d"; /* reverse of IBM order */ static char ir3[] = "R%b,R%a,R%d"; static char ir3r[] = "R%a,R%b,R%d"; static char il3[] = "R%b,R%s,R%a"; -static char il2u[] = "%I,R%s,R%a"; +static char il2u[] = "%I,R%a,R%d"; static char il3s[] = "$%k,R%s,R%a"; static char il2[] = "R%s,R%a"; static char icmp3[] = "R%a,R%b,%D"; @@ -694,12 +687,16 @@ static char ldop[] = "%l,R%d"; static char stop[] = "R%d,%l"; static char fldop[] = "%l,F%d"; static char fstop[] = "F%d,%l"; +static char rldc[] = "R%b,R%s,$%E,R%a"; static char rlim[] = "R%b,R%s,$%z,R%a"; static char rlimi[] = "$%k,R%s,$%z,R%a"; +static char rldi[] = "$%e,R%s,$%E,R%a"; #define OEM IBF(~0,22,30) #define FP4 IBF(~0,26,30) -#define ALL ((ushort)~0) +#define ALL (~0) +#define RLDC 0xF +#define RLDI 0xE /* notes: 10-26: crfD = rD>>2; rD&3 mbz @@ -707,8 +704,6 @@ notes: */ static Opcode opcodes[] = { - {31, 360, OEM, "ABS%V%C", 0, ir2}, /* POWER */ - {31, 266, OEM, "ADD%V%C", add, ir3}, {31, 10, OEM, "ADDC%V%C", add, ir3}, {31, 138, OEM, "ADDE%V%C", add, ir3}, @@ -721,22 +716,21 @@ static Opcode opcodes[] = { {31, 28, ALL, "AND%C", and, il3}, {31, 60, ALL, "ANDN%C", and, il3}, - {28, 0, 0, "ANDCC", andi, il2u}, - {29, 0, 0, "ANDCC", shifted, 0}, + {28, 0, 0, "ANDCC", andi, il2u}, + {29, 0, 0, "ANDCC", shifted, 0}, {18, 0, 0, "B%L", gencc, "%j"}, {16, 0, 0, "BC%L", branch, "%d,%a,%J"}, {19, 528, ALL, "BC%L", branch, "%d,%a,(CTR)"}, {19, 16, ALL, "BC%L", branch, "%d,%a,(LR)"}, - {31, 531, ALL, "CLCS", gen, ir2}, /* POWER */ - {31, 0, ALL, "CMP", 0, icmp3}, {11, 0, 0, "CMP", 0, "R%a,%i,%D"}, {31, 32, ALL, "CMPU", 0, icmp3}, {10, 0, 0, "CMPU", 0, "R%a,%I,%D"}, - {31, 26, ALL, "CNTLZ%C", gencc, ir2}, + {31, 58, ALL, "CNTLZD%C", gencc, ir2}, /* 64 */ + {31, 26, ALL, "CNTLZ%W%C", gencc, ir2}, {19, 257, ALL, "CRAND", gen, cr3op}, {19, 129, ALL, "CRANDN", gen, cr3op}, @@ -753,14 +747,13 @@ static Opcode opcodes[] = { {31, 278, ALL, "DCBT", dcb, 0}, {31, 246, ALL, "DCBTST", dcb, 0}, {31, 1014, ALL, "DCBZ", dcb, 0}, + {31, 454, ALL, "DCCCI", dcb, 0}, + {31, 966, ALL, "ICCCI", dcb, 0}, - {31, 331, OEM, "DIV%V%C", qmuldiv, ir3}, /* POWER */ - {31, 363, OEM, "DIVS%V%C", qmuldiv, ir3}, /* POWER */ - {31, 491, OEM, "DIVW%V%C", qmuldiv, ir3}, - {31, 459, OEM, "DIVWU%V%C", qmuldiv, ir3}, - - {31, 264, OEM, "DOZ%V%C", gencc, ir3r}, /* POWER */ - {9, 0, 0, "DOZ", gen, ir2i}, /* POWER */ + {31, 489, OEM, "DIVD%V%C", qdiv, ir3}, /* 64 */ + {31, 457, OEM, "DIVDU%V%C", qdiv, ir3}, /* 64 */ + {31, 491, OEM, "DIVW%V%C", qdiv, ir3}, + {31, 459, OEM, "DIVWU%V%C", qdiv, ir3}, {31, 310, ALL, "ECIWX", ldx, 0}, {31, 438, ALL, "ECOWX", stx, 0}, @@ -770,12 +763,16 @@ static Opcode opcodes[] = { {31, 954, ALL, "EXTSB%C", gencc, il2}, {31, 922, ALL, "EXTSH%C", gencc, il2}, + {31, 986, ALL, "EXTSW%C", gencc, il2}, /* 64 */ {63, 264, ALL, "FABS%C", gencc, fp2}, {63, 21, ALL, "FADD%C", gencc, fp3}, {59, 21, ALL, "FADDS%C", gencc, fp3}, {63, 32, ALL, "FCMPO", gen, fpcmp}, {63, 0, ALL, "FCMPU", gen, fpcmp}, + {63, 846, ALL, "FCFID%C", gencc, fp2}, /* 64 */ + {63, 814, ALL, "FCTID%C", gencc, fp2}, /* 64 */ + {63, 815, ALL, "FCTIDZ%C", gencc, fp2}, /* 64 */ {63, 14, ALL, "FCTIW%C", gencc, fp2}, {63, 15, ALL, "FCTIWZ%C", gencc, fp2}, {63, 18, ALL, "FDIV%C", gencc, fp3}, @@ -793,11 +790,16 @@ static Opcode opcodes[] = { {59, 31, FP4, "FNMADDS%C", gencc, fp4}, {63, 30, FP4, "FNMSUB%C", gencc, fp4}, {59, 30, FP4, "FNMSUBS%C", gencc, fp4}, + {59, 24, ALL, "FRES%C", gencc, fp2}, /* optional */ {63, 12, ALL, "FRSP%C", gencc, fp2}, + {63, 26, ALL, "FRSQRTE%C", gencc, fp2}, /* optional */ + {63, 23, FP4, "FSEL%CC", gencc, fp4}, /* optional */ + {63, 22, ALL, "FSQRT%C", gencc, fp2}, /* optional */ + {59, 22, ALL, "FSQRTS%C", gencc, fp2}, /* optional */ {63, 20, FP4, "FSUB%C", gencc, fp3}, {59, 20, FP4, "FSUBS%C", gencc, fp3}, - {31, 982, ALL, "ICBI", dcb, 0}, + {31, 982, ALL, "ICBI", dcb, 0}, /* optional */ {19, 150, ALL, "ISYNC", gen, 0}, {34, 0, 0, "MOVBZ", load, ldop}, @@ -822,18 +824,26 @@ static Opcode opcodes[] = { {31, 311, ALL, "MOVHZU", ldx, 0}, {31, 279, ALL, "MOVHZ", ldx, 0}, {46, 0, 0, "MOVMW", load, ldop}, - {31, 277, ALL, "LSCBX%C", ldx, 0}, /* POWER */ {31, 597, ALL, "LSW", gen, "(R%a),$%n,R%d"}, {31, 533, ALL, "LSW", ldx, 0}, {31, 20, ALL, "LWAR", ldx, 0}, + {31, 84, ALL, "LWARD", ldx, 0}, /* 64 */ + + {58, 0, ALL, "MOVD", load, ldop}, /* 64 */ + {58, 1, ALL, "MOVDU", load, ldop}, /* 64 */ + {31, 53, ALL, "MOVDU", ldx, 0}, /* 64 */ + {31, 21, ALL, "MOVD", ldx, 0}, /* 64 */ + {31, 534, ALL, "MOVWBR", ldx, 0}, - {32, 0, 0, "MOVW", load, ldop}, - {33, 0, 0, "MOVWU", load, ldop}, - {31, 55, ALL, "MOVWU", ldx, 0}, - {31, 23, ALL, "MOVW", ldx, 0}, - {31, 29, ALL, "MASKG%C", gencc, "R%s:R%b,R%d"}, /* POWER */ - {31, 541, ALL, "MASKIR%C", gencc, "R%s,R%b,R%a"}, /* POWER */ + {58, 2, ALL, "MOVW", load, ldop}, /* 64 (lwa) */ + {31, 373, ALL, "MOVWU", ldx, 0}, /* 64 */ + {31, 341, ALL, "MOVW", ldx, 0}, /* 64 */ + + {32, 0, 0, "MOVW%Z", load, ldop}, + {33, 0, 0, "MOVW%ZU", load, ldop}, + {31, 55, ALL, "MOVW%ZU", ldx, 0}, + {31, 23, ALL, "MOVW%Z", ldx, 0}, {19, 0, ALL, "MOVFL", gen, "%S,%D"}, {63, 64, ALL, "MOVCRFS", gen, "%S,%D"}, @@ -845,67 +855,63 @@ static Opcode opcodes[] = { {31, 339, ALL, "MOVW", gen, "%P,R%d"}, {31, 595, ALL, "MOVW", gen, "SEG(%a),R%d"}, {31, 659, ALL, "MOVW", gen, "SEG(R%b),R%d"}, + {31, 323, ALL, "MOVW", gen, "DCR(%Q),R%d"}, + {31, 451, ALL, "MOVW", gen, "R%s,DCR(%Q)"}, {31, 144, ALL, "MOVFL", gen, "R%s,%m,CR"}, {63, 70, ALL, "MTFSB0%C", gencc, "%D"}, {63, 38, ALL, "MTFSB1%C", gencc, "%D"}, {63, 711, ALL, "MOVFL%C", gencc, "F%b,%M,FPSCR"}, /* mtfsf */ {63, 134, ALL, "MOVFL%C", gencc, "%K,%D"}, {31, 146, ALL, "MOVW", gen, "R%s,MSR"}, + {31, 178, ALL, "MOVD", gen, "R%s,MSR"}, {31, 467, ALL, "MOVW", gen, "R%s,%P"}, {31, 210, ALL, "MOVW", gen, "R%s,SEG(%a)"}, {31, 242, ALL, "MOVW", gen, "R%s,SEG(R%b)"}, - {31, 107, OEM, "MUL%V%C", gencc, ir3}, /* POWER */ - {31, 75, ALL, "MULHW%C", gencc, ir3}, /* POWER */ - {31, 11, ALL, "MULHWU%C", gencc, ir3}, /* POWER */ + {31, 73, ALL, "MULHD%C", gencc, ir3}, + {31, 9, ALL, "MULHDU%C", gencc, ir3}, + {31, 233, OEM, "MULLD%V%C", gencc, ir3}, + {31, 75, ALL, "MULHW%C", gencc, ir3}, + {31, 11, ALL, "MULHWU%C", gencc, ir3}, {31, 235, OEM, "MULLW%V%C", gencc, ir3}, - {7, 0, 0, "MULLW", qmuldiv, "%i,R%a,R%d"}, - {31, 488, OEM, "NABS%V%C", neg, ir2}, /* POWER */ + {7, 0, 0, "MULLW", qdiv, "%i,R%a,R%d"}, {31, 476, ALL, "NAND%C", gencc, il3}, {31, 104, OEM, "NEG%V%C", neg, ir2}, {31, 124, ALL, "NOR%C", gencc, il3}, - {31, 444, ALL, "OR%C", or, il3}, + {31, 444, ALL, "OR%C", or, il3}, {31, 412, ALL, "ORN%C", or, il3}, {24, 0, 0, "OR", and, "%I,R%d,R%a"}, {25, 0, 0, "OR", shifted, 0}, {19, 50, ALL, "RFI", gen, 0}, + {19, 51, ALL, "RFCI", gen, 0}, + + {30, 8, RLDC, "RLDCL%C", gencc, rldc}, /* 64 */ + {30, 9, RLDC, "RLDCR%C", gencc, rldc}, /* 64 */ + {30, 0, RLDI, "RLDCL%C", gencc, rldi}, /* 64 */ + {30, 1<<1, RLDI, "RLDCR%C", gencc, rldi}, /* 64 */ + {30, 2<<1, RLDI, "RLDC%C", gencc, rldi}, /* 64 */ + {30, 3<<1, RLDI, "RLDMI%C", gencc, rldi}, /* 64 */ - {22, 0, 0, "RLMI%C", gencc, rlim}, /* POWER */ {20, 0, 0, "RLWMI%C", gencc, rlimi}, {21, 0, 0, "RLWNM%C", gencc, rlimi}, {23, 0, 0, "RLWNM%C", gencc, rlim}, - {31, 537, ALL, "RRIB%C", gencc, il3}, /* POWER */ - {17, 1, ALL, "SYSCALL", gen, 0}, - {31, 153, ALL, "SLE%C", shift, il3}, /* POWER */ - {31, 217, ALL, "SLEQ%C", shift, il3}, /* POWER */ - {31, 184, ALL, "SLQ%C", shifti, il3s}, /* POWER */ - {31, 248, ALL, "SLLQ%C", shifti, il3s}, /* POWER */ - {31, 216, ALL, "SLLQ%C", shift, il3}, /* POWER */ - {31, 152, ALL, "SLQ%C", shift, il3}, /* POWER */ - + {31, 27, ALL, "SLD%C", shift, il3}, /* 64 */ {31, 24, ALL, "SLW%C", shift, il3}, - {31, 920, ALL, "SRAQ%C", shift, il3}, /* POWER */ - {31, 952, ALL, "SRAQ%C", shifti, il3s}, /* POWER */ - + {31, 794, ALL, "SRAD%C", shift, il3}, /* 64 */ + {31, (413<<1)|0, ALL, "SRAD%C", shifti, il3s}, /* 64 */ + {31, (413<<1)|1, ALL, "SRAD%C", shifti, il3s}, /* 64 */ {31, 792, ALL, "SRAW%C", shift, il3}, {31, 824, ALL, "SRAW%C", shifti, il3s}, - {31, 665, ALL, "SRE%C", shift, il3}, /* POWER */ - {31, 921, ALL, "SREA%C", shift, il3}, /* POWER */ - {31, 729, ALL, "SREQ%C", shift, il3}, /* POWER */ - {31, 696, ALL, "SRQ%C", shifti, il3s}, /* POWER */ - {31, 760, ALL, "SRLQ%C", shifti, il3s}, /* POWER */ - {31, 728, ALL, "SRLQ%C", shift, il3}, /* POWER */ - {31, 664, ALL, "SRQ%C", shift, il3}, /* POWER */ - + {31, 539, ALL, "SRD%C", shift, il3}, /* 64 */ {31, 536, ALL, "SRW%C", shift, il3}, {38, 0, 0, "MOVB", store, stop}, @@ -931,10 +937,22 @@ static Opcode opcodes[] = { {36, 0, 0, "MOVW", store, stop}, {31, 662, ALL, "MOVWBR", stx, 0}, {31, 150, ALL, "STWCCC", stx, 0}, + {31, 214, ALL, "STDCCC", stx, 0}, /* 64 */ {37, 0, 0, "MOVWU", store, stop}, {31, 183, ALL, "MOVWU", stx, 0}, {31, 151, ALL, "MOVW", stx, 0}, + {62, 0, 0, "MOVD%U", store, stop}, /* 64 */ + {31, 149, ALL, "MOVD", stx, 0,}, /* 64 */ + {31, 181, ALL, "MOVDU", stx, 0}, /* 64 */ + + {31, 498, ALL, "SLBIA", gen, 0}, /* 64 */ + {31, 434, ALL, "SLBIE", gen, "R%b"}, /* 64 */ + {31, 466, ALL, "SLBIEX", gen, "R%b"}, /* 64 */ + {31, 915, ALL, "SLBMFEE", gen, "R%b,R%d"}, /* 64 */ + {31, 851, ALL, "SLBMFEV", gen, "R%b,R%d"}, /* 64 */ + {31, 402, ALL, "SLBMTE", gen, "R%s,R%b"}, /* 64 */ + {31, 40, OEM, "SUB%V%C", sub, ir3}, {31, 8, OEM, "SUBC%V%C", sub, ir3}, {31, 136, OEM, "SUBE%V%C", sub, ir3}, @@ -942,11 +960,15 @@ static Opcode opcodes[] = { {31, 232, OEM, "SUBME%V%C", sub, ir2}, {31, 200, OEM, "SUBZE%V%C", sub, ir2}, - {31, 598, ALL, "SYNC", gen, 0}, - {31, 306, ALL, "TLBIE", gen, "R%b"}, - {31, 370, ALL, "TLBIA", gen, 0}, - {31, 1010, ALL, "TLBLI", gen, "R%b"}, - {31, 978, ALL, "TLBLD", gen, "R%b"}, + {31, 598, ALL, "SYNC", gen, 0}, /* TO DO: there's a parameter buried in there */ + {2, 0, 0, "TD", gen, "%d,R%a,%i"}, /* 64 */ + {31, 370, ALL, "TLBIA", gen, 0}, /* optional */ + {31, 306, ALL, "TLBIE", gen, "R%b"}, /* optional */ + {31, 274, ALL, "TLBIEL", gen, "R%b"}, /* optional */ + {31, 1010, ALL, "TLBLI", gen, "R%b"}, /* optional */ + {31, 978, ALL, "TLBLD", gen, "R%b"}, /* optional */ + {31, 566, ALL, "TLBSYNC", gen, 0}, /* optional */ + {31, 68, ALL, "TD", gen, "%d,R%a,R%b"}, /* 64 */ {31, 4, ALL, "TW", gen, "%d,R%a,R%b"}, {3, 0, 0, "TW", gen, "%d,R%a,%i"}, @@ -1013,11 +1035,31 @@ static Spr sprname[] = { {0,0}, }; +static int +shmask(uvlong *m) +{ + int i; + + for(i=0; i<63; i++) + if(*m & ((uvlong)1<<i)) + break; + if(i > 63) + return 0; + if(*m & ~((uvlong)1<<i)){ /* more than one bit: do multiples of bytes */ + i = (i/8)*8; + if(i == 0) + return 0; + } + *m >>= i; + return i; +} + static void format(char *mnemonic, Instr *i, char *f) { int n, s; ulong mask; + uvlong vmask; if (mnemonic) format(0, i, mnemonic); @@ -1031,15 +1073,6 @@ format(char *mnemonic, Instr *i, char *f) continue; } switch (*++f) { - case 'V': - if(i->oe) - bprint(i, "V"); - break; - - case 'C': - if(i->rc) - bprint(i, "CC"); - break; case 'a': bprint(i, "%d", i->ra); @@ -1058,13 +1091,9 @@ format(char *mnemonic, Instr *i, char *f) bprint(i, "%d", i->rd); break; - case 'S': - if(i->ra & 3) - bprint(i, "CR(INVAL:%d)", i->ra); - else if(i->op == 63) - bprint(i, "FPSCR(%d)", i->crfs); - else - bprint(i, "CR(%d)", i->crfs); + case 'C': + if(i->rc) + bprint(i, "CC"); break; case 'D': @@ -1076,20 +1105,83 @@ format(char *mnemonic, Instr *i, char *f) bprint(i, "CR(%d)", i->crfd); break; - case 'l': - address(i); + case 'e': + bprint(i, "%d", i->xsh); + break; + + case 'E': + switch(IBF(i->w0,27,30)){ /* low bit is top bit of shift in rldiX cases */ + case 8: i->mb = i->xmbe; i->me = 63; break; /* rldcl */ + case 9: i->mb = 0; i->me = i->xmbe; break; /* rldcr */ + case 4: case 5: + i->mb = i->xmbe; i->me = 63-i->xsh; break; /* rldic */ + case 0: case 1: + i->mb = i->xmbe; i->me = 63; break; /* rldicl */ + case 2: case 3: + i->mb = 0; i->me = i->xmbe; break; /* rldicr */ + case 6: case 7: + i->mb = i->xmbe; i->me = 63-i->xsh; break; /* rldimi */ + } + vmask = (~(uvlong)0>>i->mb) & (~(uvlong)0<<(63-i->me)); + s = shmask(&vmask); + if(s) + bprint(i, "(%llux<<%d)", vmask, s); + else + bprint(i, "%llux", vmask); break; case 'i': - bprint(i, "$%ld", i->simm); + bprint(i, "$%d", i->simm); break; case 'I': - bprint(i, "$%lx", i->uimm); + bprint(i, "$%ux", i->uimm); break; - case 'w': - bprint(i, "[%lux]", i->w0); + case 'j': + if(i->aa) + pglobal(i, i->li, 1, "(SB)"); + else + pglobal(i, i->addr+i->li, 1, ""); + break; + + case 'J': + if(i->aa) + pglobal(i, i->bd, 1, "(SB)"); + else + pglobal(i, i->addr+i->bd, 1, ""); + break; + + case 'k': + bprint(i, "%d", i->sh); + break; + + case 'K': + bprint(i, "$%x", i->imm); + break; + + case 'L': + if(i->lk) + bprint(i, "L"); + break; + + case 'l': + if(i->simm < 0) + bprint(i, "-%x(R%d)", -i->simm, i->ra); + else + bprint(i, "%x(R%d)", i->simm, i->ra); + break; + + case 'm': + bprint(i, "%ux", i->crm); + break; + + case 'M': + bprint(i, "%ux", i->fm); + break; + + case 'n': + bprint(i, "%d", i->nb==0? 32: i->nb); /* eg, pg 10-103 */ break; case 'P': @@ -1098,7 +1190,7 @@ format(char *mnemonic, Instr *i, char *f) if(sprname[s].n == n) break; if(sprname[s].name) { - if(n < 10) + if(s < 10) bprint(i, sprname[s].name); else bprint(i, "SPR(%s)", sprname[s].name); @@ -1106,51 +1198,50 @@ format(char *mnemonic, Instr *i, char *f) bprint(i, "SPR(%d)", n); break; - case 'n': - bprint(i, "%d", i->nb==0? 32: i->nb); /* eg, pg 10-103 */ - break; - - case 'm': - bprint(i, "%lx", i->crm); + case 'Q': + n = ((i->spr&0x1f)<<5)|((i->spr>>5)&0x1f); + bprint(i, "%d", n); break; - case 'M': - bprint(i, "%lx", i->fm); + case 'S': + if(i->ra & 3) + bprint(i, "CR(INVAL:%d)", i->ra); + else if(i->op == 63) + bprint(i, "FPSCR(%d)", i->crfs); + else + bprint(i, "CR(%d)", i->crfs); break; - case 'z': - if(i->mb <= i->me) - mask = ((ulong)~0L>>i->mb) & (~0L<<(31-i->me)); - else - mask = ~(((ulong)~0L>>(i->me+1)) & (~0L<<(31-(i->mb-1)))); - bprint(i, "%lux", mask); + case 'U': + if(i->rc) + bprint(i, "U"); break; - case 'k': - bprint(i, "%d", i->sh); + case 'V': + if(i->oe) + bprint(i, "V"); break; - case 'K': - bprint(i, "$%x", i->imm); + case 'w': + bprint(i, "[%lux]", i->w0); break; - case 'L': - if(i->lk) - bprint(i, "L"); + case 'W': + if(i->m64) + bprint(i, "W"); break; - case 'j': - if(i->aa) - pglobal(i, i->li, 1, "(SB)"); - else - pglobal(i, i->addr+i->li, 1, ""); + case 'Z': + if(i->m64) + bprint(i, "Z"); break; - case 'J': - if(i->aa) - pglobal(i, i->bd, 1, "(SB)"); + case 'z': + if(i->mb <= i->me) + mask = ((ulong)~0L>>i->mb) & (~0L<<(31-i->me)); else - pglobal(i, i->addr+i->bd, 1, ""); + mask = ~(((ulong)~0L>>(i->me+1)) & (~0L<<(31-(i->mb-1)))); + bprint(i, "%lux", mask); break; case '\0': @@ -1165,7 +1256,7 @@ format(char *mnemonic, Instr *i, char *f) } static int -printins(Map *map, ulong pc, char *buf, int n) +printins(Map *map, uvlong pc, char *buf, int n) { Instr i; Opcode *o; @@ -1189,14 +1280,14 @@ printins(Map *map, ulong pc, char *buf, int n) } static int -powerinst(Map *map, ulong pc, char modifier, char *buf, int n) +powerinst(Map *map, uvlong pc, char modifier, char *buf, int n) { USED(modifier); return printins(map, pc, buf, n); } static int -powerdas(Map *map, ulong pc, char *buf, int n) +powerdas(Map *map, uvlong pc, char *buf, int n) { Instr instr; @@ -1217,7 +1308,7 @@ powerdas(Map *map, ulong pc, char *buf, int n) } static int -powerinstlen(Map *map, ulong pc) +powerinstlen(Map *map, uvlong pc) { Instr i; @@ -1228,7 +1319,7 @@ powerinstlen(Map *map, ulong pc) } static int -powerfoll(Map *map, ulong pc, Rgetter rget, ulong *foll) +powerfoll(Map *map, uvlong pc, Rgetter rget, uvlong *foll) { char *reg; Instr i; diff --git a/utils/libmach/qobj.c b/utils/libmach/qobj.c index 5decad08..e5a2222b 100644 --- a/utils/libmach/qobj.c +++ b/utils/libmach/qobj.c @@ -4,6 +4,7 @@ */ #include <lib9.h> #include <bio.h> +#include <mach.h> #include "qc/q.out.h" #include "obj.h" @@ -21,25 +22,33 @@ static void skip(Biobuf*, int); int _isq(char *s) { - return (s[0]&0377) == ANAME /* ANAME */ - && s[1] == D_FILE /* type */ - && s[2] == 1 /* sym */ - && s[3] == '<'; /* name of file */ + return (s[0]&0377) == ANAME /* ANAME */ + && (s[1]&0377) == ANAME>>8 + && s[2] == D_FILE /* type */ + && s[3] == 1 /* sym */ + && s[4] == '<'; /* name of file */ } int _readq(Biobuf *bp, Prog *p) { - int as, n; + int as, n, c; Addr a; - as = Bgetc(bp); /* as */ + as = Bgetc(bp); /* as(low) */ if(as < 0) return 0; + c = Bgetc(bp); /* as(high) */ + if(c < 0) + return 0; + as |= ((c & 0xff) << 8); p->kind = aNone; + p->sig = 0; if(as == ANAME || as == ASIGNAME){ - if(as == ASIGNAME) - skip(bp, 4); /* signature */ + if(as == ASIGNAME){ + Bread(bp, &p->sig, 4); + p->sig = beswal(p->sig); + } p->kind = aName; p->type = type2char(Bgetc(bp)); /* type */ p->sym = Bgetc(bp); /* sym */ @@ -93,6 +102,7 @@ addr(Biobuf *bp) break; case D_SPR: case D_OREG: + case D_DCR: case D_CONST: case D_BRANCH: off = Bgetc(bp); diff --git a/utils/libmach/swap.c b/utils/libmach/swap.c index 3ca9cf27..63f76293 100644 --- a/utils/libmach/swap.c +++ b/utils/libmach/swap.c @@ -1,4 +1,6 @@ #include <lib9.h> +#include <bio.h> +#include "mach.h" /* * big-endian short @@ -15,8 +17,8 @@ beswab(ushort s) /* * big-endian long */ -long -beswal(long l) +ulong +beswal(ulong l) { uchar *p; @@ -27,16 +29,16 @@ beswal(long l) /* * big-endian vlong */ -vlong -beswav(vlong v) +uvlong +beswav(uvlong v) { uchar *p; p = (uchar*)&v; - return ((vlong)p[0]<<56) | ((vlong)p[1]<<48) | ((vlong)p[2]<<40) - | ((vlong)p[3]<<32) | ((vlong)p[4]<<24) - | ((vlong)p[5]<<16) | ((vlong)p[6]<<8) - | (vlong)p[7]; + return ((uvlong)p[0]<<56) | ((uvlong)p[1]<<48) | ((uvlong)p[2]<<40) + | ((uvlong)p[3]<<32) | ((uvlong)p[4]<<24) + | ((uvlong)p[5]<<16) | ((uvlong)p[6]<<8) + | (uvlong)p[7]; } /* @@ -54,8 +56,8 @@ leswab(ushort s) /* * little-endian long */ -long -leswal(long l) +ulong +leswal(ulong l) { uchar *p; @@ -66,14 +68,14 @@ leswal(long l) /* * little-endian vlong */ -vlong -leswav(vlong v) +uvlong +leswav(uvlong v) { uchar *p; p = (uchar*)&v; - return ((vlong)p[7]<<56) | ((vlong)p[6]<<48) | ((vlong)p[5]<<40) - | ((vlong)p[4]<<32) | ((vlong)p[3]<<24) - | ((vlong)p[2]<<16) | ((vlong)p[1]<<8) - | (vlong)p[0]; + return ((uvlong)p[7]<<56) | ((uvlong)p[6]<<48) | ((uvlong)p[5]<<40) + | ((uvlong)p[4]<<32) | ((uvlong)p[3]<<24) + | ((uvlong)p[2]<<16) | ((uvlong)p[1]<<8) + | (uvlong)p[0]; } diff --git a/utils/libmach/sym.c b/utils/libmach/sym.c index 476e5e3d..751d933d 100644 --- a/utils/libmach/sym.c +++ b/utils/libmach/sym.c @@ -8,7 +8,6 @@ typedef struct txtsym Txtsym; typedef struct file File; typedef struct hist Hist; -typedef struct pcl Pcl; struct txtsym { /* Text Symbol table */ int n; /* number of local vars */ @@ -16,27 +15,20 @@ struct txtsym { /* Text Symbol table */ Sym *sym; /* function symbol entry */ }; -struct hist { /* Stack of include files & #line directives */ +struct hist { /* Stack of include files & #line directives */ char *name; /* Assumes names Null terminated in file */ long line; /* line # where it was included */ long offset; /* line # of #line directive */ }; -struct pcl { - uchar *pcline; /* start of pcline data for this file */ - long pc; /* starting pc for pcline crunch */ - long line; /* starting line for pcline crunch */ -}; - struct file { /* Per input file header to history stack */ - long addr; /* address of first text sym */ - union { - Txtsym *ftxt; /* first text symbol */ - Sym *fsym; /* only during initilization */ - } u0; - int n; /* size of history stack */ - Hist *hist; /* history stack */ - Pcl pcl; /* pcline startup data */ + uvlong addr; /* address of first text sym */ + /* union { */ + Txtsym *txt; /* first text symbol */ + Sym *sym; /* only during initilization */ + /* }; */ + int n; /* size of history stack */ + Hist *hist; /* history stack */ }; static int debug = 0; @@ -53,19 +45,18 @@ static long nfiles; /* number of files */ static long nglob; /* number of globals */ static long nhist; /* number of history stack entries */ static long nsym; /* number of symbols */ -static long ntxt; /* number of text symbols */ +static int ntxt; /* number of text symbols */ static uchar *pcline; /* start of pc-line state table */ static uchar *pclineend; /* end of pc-line table */ -static int npcl; /* number of files pcl-decoded so far */ static uchar *spoff; /* start of pc-sp state table */ static uchar *spoffend; /* end of pc-sp offset table */ static Sym *symbols; /* symbol table */ static Txtsym *txt; /* Base of text symbol table */ -static long txtstart; /* start of text segment */ -static long txtend; /* end of text segment */ +static uvlong txtstart; /* start of text segment */ +static uvlong txtend; /* end of text segment */ static void cleansyms(void); -static int decodename(Biobuf*, Sym*); +static long decodename(Biobuf*, Sym*); static short *encfname(char*); static int fline(char*, int, long, Hist*, Hist**); static void fillsym(Sym*, Symbol*); @@ -73,11 +64,8 @@ static int findglobal(char*, Symbol*); static int findlocvar(Symbol*, char *, Symbol*); static int findtext(char*, Symbol*); static int hcomp(Hist*, short*); -static int hline(File*, short*, ulong*); +static int hline(File*, short*, long*); static void printhist(char*, Hist*, int); -static long pcl2line(ulong, Pcl *, Pcl *); -static long pc2fline(ulong, File **); -static int pc2filex(ulong); static int buildtbls(void); static int symcomp(void*, void*); static int symerrmsg(int, char*); @@ -91,9 +79,10 @@ int syminit(int fd, Fhdr *fp) { Sym *p; - int i, size; + long i, l, size; + vlong vl; Biobuf b; - extern void thumbpctab(Biobuf*, Fhdr*); + int svalsz; if(fp->symsz == 0) return 0; @@ -108,22 +97,30 @@ syminit(int fd, Fhdr *fp) werrstr("can't malloc %ld bytes", fp->symsz); return -1; } - Binit(&b, fd, OREAD); Bseek(&b, fp->symoff, 0); nsym = 0; size = 0; for(p = symbols; size < fp->symsz; p++, nsym++) { - if(Bread(&b, &p->value, sizeof(p->value)) != sizeof(p->value)) - return symerrmsg(sizeof(p->value), "symbol"); - p->value = beswal(p->value); + if(fp->_magic && (fp->magic & HDR_MAGIC)){ + svalsz = 8; + if(Bread(&b, &vl, 8) != 8) + return symerrmsg(8, "symbol"); + p->value = beswav(vl); + } + else{ + svalsz = 4; + if(Bread(&b, &l, 4) != 4) + return symerrmsg(4, "symbol"); + p->value = (u32int)beswal(l); + } if(Bread(&b, &p->type, sizeof(p->type)) != sizeof(p->type)) return symerrmsg(sizeof(p->value), "symbol"); i = decodename(&b, p); if(i < 0) return -1; - size += i+sizeof(p->value)+sizeof(p->type); + size += i+svalsz+sizeof(p->type); /* count global & auto vars, text symbols, and file names */ switch (p->type) { @@ -164,7 +161,7 @@ syminit(int fd, Fhdr *fp) } } if (debug) - fprint(2,"NG: %ld NT: %ld NF: %d\n", nglob, ntxt, fpmax); + print("NG: %ld NT: %d NF: %d\n", nglob, ntxt, fpmax); if (fp->sppcsz) { /* pc-sp offset table */ spoff = (uchar *)malloc(fp->sppcsz); if(spoff == 0) { @@ -172,8 +169,7 @@ syminit(int fd, Fhdr *fp) return -1; } Bseek(&b, fp->sppcoff, 0); - i = Bread(&b, spoff, fp->sppcsz); - if(i != fp->sppcsz){ + if(Bread(&b, spoff, fp->sppcsz) != fp->sppcsz){ spoff = 0; return symerrmsg(fp->sppcsz, "sp-pc"); } @@ -186,8 +182,7 @@ syminit(int fd, Fhdr *fp) return -1; } Bseek(&b, fp->lnpcoff, 0); - i = Bread(&b, pcline, fp->lnpcsz); - if(i != fp->lnpcsz){ + if(Bread(&b, pcline, fp->lnpcsz) != fp->lnpcsz){ pcline = 0; return symerrmsg(fp->lnpcsz, "pc-line"); } @@ -205,12 +200,13 @@ symerrmsg(int n, char *table) return -1; } -static int +static long decodename(Biobuf *bp, Sym *p) { char *cp; int c1, c2; - int n; + long n; + vlong o; if((p->type & 0x80) == 0) { /* old-style, fixed length names */ p->name = malloc(NNAME); @@ -226,7 +222,7 @@ decodename(Biobuf *bp, Sym *p) p->type &= ~0x80; if(p->type == 'z' || p->type == 'Z') { - n = Bseek(bp, 0, 1); + o = Bseek(bp, 0, 1); if(Bgetc(bp) < 0) { werrstr("can't read symbol name"); return -1; @@ -241,15 +237,15 @@ decodename(Biobuf *bp, Sym *p) if(c1 == 0 && c2 == 0) break; } - n = Bseek(bp, 0, 1)-n; + n = Bseek(bp, 0, 1)-o; p->name = malloc(n); if(p->name == 0) { - werrstr("can't malloc %d bytes", n); + werrstr("can't malloc %ld bytes", n); return -1; } Bseek(bp, -n, 1); if(Bread(bp, p->name, n) != n) { - werrstr("can't read %d bytes of symbol name", n); + werrstr("can't read %ld bytes of symbol name", n); return -1; } } else { @@ -261,13 +257,14 @@ decodename(Biobuf *bp, Sym *p) n = Blinelen(bp); p->name = malloc(n); if(p->name == 0) { - werrstr("can't malloc %d bytes", n); + werrstr("can't malloc %ld bytes", n); return -1; } strcpy(p->name, cp); } return n; } + /* * free any previously loaded symbol tables */ @@ -310,18 +307,18 @@ cleansyms(void) if(pcline) free(pcline); pcline = 0; - npcl = 0; } + /* * delimit the text segment */ void -textseg(ulong base, Fhdr *fp) +textseg(uvlong base, Fhdr *fp) { txtstart = base; txtend = base+fp->txtsz; - npcl = 0; /* all pcls must be recomputed */ } + /* * symbase: return base and size of raw symbol table * (special hack for high access rate operations) @@ -332,13 +329,14 @@ symbase(long *n) *n = nsym; return symbols; } + /* * Get the ith symbol table entry */ Sym * getsym(int index) { - if(index < nsym) + if(index >= 0 && index < nsym) return &symbols[index]; return 0; } @@ -349,7 +347,8 @@ getsym(int index) static int buildtbls(void) { - int i, j, nh, ng, nt; + long i; + int j, nh, ng, nt; File *f; Txtsym *tp; Hist *hp; @@ -373,13 +372,12 @@ buildtbls(void) return 0; } } - fpmax++; - fnames = malloc(fpmax*sizeof(*fnames)); + fnames = malloc((fpmax+1)*sizeof(*fnames)); if (!fnames) { werrstr("can't malloc file name table"); return 0; } - memset(fnames, 0, fpmax*sizeof(*fnames)); + memset(fnames, 0, (fpmax+1)*sizeof(*fnames)); files = malloc(nfiles*sizeof(*files)); if(!files) { werrstr("can't malloc file table"); @@ -409,7 +407,7 @@ buildtbls(void) case 'B': case 'b': if(debug) - fprint(2,"Global: %s %lux\n", p->name, p->value); + print("Global: %s %llux\n", p->name, p->value); globals[ng++] = p; break; case 'z': @@ -420,9 +418,10 @@ buildtbls(void) hp += nh+1; f++; } - else f = files; + else + f = files; f->hist = hp; - f->u0.fsym = 0; + f->sym = 0; f->addr = 0; nh = 0; } @@ -447,9 +446,9 @@ buildtbls(void) tp->sym = p; tp->locals = ap; if(debug) - fprint(2,"TEXT: %s at %lux\n", p->name, p->value); - if(f && !f->u0.fsym) { /* first */ - f->u0.fsym = p; + print("TEXT: %s at %llux\n", p->name, p->value); + if(f && !f->sym) { /* first */ + f->sym = p; f->addr = p->value; } break; @@ -457,10 +456,11 @@ buildtbls(void) case 'p': case 'm': /* Local Vars */ if(!tp) - print("Warning: Free floating local var"); + print("Warning: Free floating local var: %s\n", + p->name); else { if(debug) - fprint(2,"Local: %s %lux\n", p->name, p->value); + print("Local: %s %llux\n", p->name, p->value); tp->locals[tp->n] = p; tp->n++; ap++; @@ -468,7 +468,7 @@ buildtbls(void) break; case 'f': /* File names */ if(debug) - fprint(2,"Fname: %s\n", p->name); + print("Fname: %s\n", p->name); fnames[p->value] = p; break; default: @@ -482,12 +482,12 @@ buildtbls(void) tp = txt; for(i = 0, f = files; i < nfiles; i++, f++) { for(j = 0; j < ntxt; j++) { - if(f->u0.fsym == tp->sym) { + if(f->sym == tp->sym) { if(debug) { - fprint(2,"LINK: %s to at %lux", f->u0.fsym->name, f->addr); + print("LINK: %s to at %llux", f->sym->name, f->addr); printhist("... ", f->hist, 1); } - f->u0.ftxt = tp++; + f->txt = tp++; break; } if(++tp >= txt+ntxt) /* wrap around */ @@ -527,6 +527,7 @@ lookup(char *fn, char *var, Symbol *s) return findglobal(var, s); /* case 3: var not found */ } + /* * find a function by name */ @@ -539,6 +540,7 @@ findtext(char *name, Symbol *s) if(strcmp(txt[i].sym->name, name) == 0) { fillsym(txt[i].sym, s); s->handle = (void *) &txt[i]; + s->index = i; return 1; } } @@ -550,16 +552,18 @@ findtext(char *name, Symbol *s) static int findglobal(char *name, Symbol *s) { - int i; + long i; for(i = 0; i < nglob; i++) { if(strcmp(globals[i]->name, name) == 0) { fillsym(globals[i], s); + s->index = i; return 1; } } return 0; } + /* * find the local variable by name within a given function */ @@ -572,6 +576,7 @@ findlocal(Symbol *s1, char *name, Symbol *s2) return 0; return findlocvar(s1, name, s2); } + /* * find the local variable by name within a given function * (internal function - does no parameter validation) @@ -588,11 +593,13 @@ findlocvar(Symbol *s1, char *name, Symbol *s2) if (strcmp(tp->locals[i]->name, name) == 0) { fillsym(tp->locals[i], s2); s2->handle = (void *)tp; + s2->index = tp->n-1 - i; return 1; } } return 0; } + /* * Get ith text symbol */ @@ -602,12 +609,14 @@ textsym(Symbol *s, int index) if(buildtbls() == 0) return 0; - if(index >= ntxt) + if(index < 0 || index >= ntxt) return 0; fillsym(txt[index].sym, s); s->handle = (void *)&txt[index]; + s->index = index; return 1; } + /* * Get ith file name */ @@ -618,13 +627,14 @@ filesym(int index, char *buf, int n) if(buildtbls() == 0) return 0; - if(index >= nfiles) + if(index < 0 || index >= nfiles) return 0; hp = files[index].hist; if(!hp || !hp->name) return 0; return fileelem(fnames, (uchar*)hp->name, buf, n); } + /* * Lookup name of local variable located at an offset into the frame. * The type selects either a parameter or automatic. @@ -654,6 +664,7 @@ getauto(Symbol *s1, int off, int type, Symbol *s2) if(p->type == t && p->value == off) { fillsym(p, s2); s2->handle = s1->handle; + s2->index = tp->n-1 - i; return 1; } } @@ -664,9 +675,9 @@ getauto(Symbol *s1, int off, int type, Symbol *s2) * Find text symbol containing addr; binary search assumes text array is sorted by addr */ static int -srchtext(long addr) +srchtext(uvlong addr) { - ulong val; + uvlong val; int top, bot, mid; Sym *sp; @@ -675,9 +686,9 @@ srchtext(long addr) top = ntxt; for (mid = (bot+top)/2; mid < top; mid = (bot+top)/2) { sp = txt[mid].sym; - if(val < (ulong)sp->value) + if(val < sp->value) top = mid; - else if(mid != ntxt-1 && val >= (ulong)txt[mid+1].sym->value) + else if(mid != ntxt-1 && val >= txt[mid+1].sym->value) bot = mid; else return mid; @@ -688,10 +699,10 @@ srchtext(long addr) /* * Find data symbol containing addr; binary search assumes data array is sorted by addr */ -static -int srchdata(long addr) +static int +srchdata(uvlong addr) { - ulong val; + uvlong val; int top, bot, mid; Sym *sp; @@ -700,15 +711,16 @@ int srchdata(long addr) val = addr; for(mid = (bot+top)/2; mid < top; mid = (bot+top)/2) { sp = globals[mid]; - if(val < (ulong)sp->value) + if(val < sp->value) top = mid; - else if(mid < nglob-1 && val >= (ulong)globals[mid+1]->value) + else if(mid < nglob-1 && val >= globals[mid+1]->value) bot = mid; else return mid; } return -1; } + /* * Find symbol containing val in specified search space * There is a special case when a value falls beyond the end @@ -717,7 +729,7 @@ int srchdata(long addr) * data space are searched for a match. */ int -findsym(long w, int type, Symbol *s) +findsym(uvlong val, int type, Symbol *s) { int i; @@ -725,19 +737,21 @@ findsym(long w, int type, Symbol *s) return 0; if(type == CTEXT || type == CANY) { - i = srchtext(w); + i = srchtext(val); if(i >= 0) { if(type == CTEXT || i != ntxt-1) { fillsym(txt[i].sym, s); s->handle = (void *) &txt[i]; + s->index = i; return 1; } } } if(type == CDATA || type == CANY) { - i = srchdata(w); + i = srchdata(val); if(i >= 0) { fillsym(globals[i], s); + s->index = i; return 1; } } @@ -748,7 +762,7 @@ findsym(long w, int type, Symbol *s) * Find the start and end address of the function containing addr */ int -fnbound(long addr, ulong *bounds) +fnbound(uvlong addr, uvlong *bounds) { int i; @@ -774,7 +788,7 @@ localsym(Symbol *s, int index) { Txtsym *tp; - if(s == 0) + if(s == 0 || index < 0) return 0; if(buildtbls() == 0) return 0; @@ -783,10 +797,12 @@ localsym(Symbol *s, int index) if(tp && tp->locals && index < tp->n) { fillsym(tp->locals[tp->n-index-1], s); /* reverse */ s->handle = (void *)tp; + s->index = index; return 1; } return 0; } + /* * get the ith global symbol */ @@ -798,30 +814,31 @@ globalsym(Symbol *s, int index) if(buildtbls() == 0) return 0; - if(index < nglob) { + if(index >=0 && index < nglob) { fillsym(globals[index], s); + s->index = index; return 1; } return 0; } + /* * find the pc given a file name and line offset into it. */ -long -file2pc(char *file, ulong line) +uvlong +file2pc(char *file, long line) { File *fp; - int i; - long pc; - ulong start, end; + long i; + uvlong pc, start, end; short *name; if(buildtbls() == 0 || files == 0) - return -1; + return ~0; name = encfname(file); if(name == 0) { /* encode the file name */ werrstr("file %s not found", file); - return -1; + return ~0; } /* find this history stack */ for(i = 0, fp = files; i < nfiles; i++, fp++) @@ -830,7 +847,7 @@ file2pc(char *file, ulong line) free(name); if(i >= nfiles) { werrstr("line %ld in file %s not found", line, file); - return -1; + return ~0; } start = fp->addr; /* first text addr this file */ if(i < nfiles-1) @@ -842,14 +859,15 @@ file2pc(char *file, ulong line) * run the state machine to locate the pc closest to that value. */ if(debug) - fprint(2,"find pc for %ld - between: %lux and %lux\n", line, start, end); + print("find pc for %ld - between: %llux and %llux\n", line, start, end); pc = line2addr(line, start, end); - if(pc == -1) { + if(pc == ~0) { werrstr("line %ld not in file %s", line, file); - return -1; + return ~0; } return pc; } + /* * search for a path component index */ @@ -859,10 +877,11 @@ pathcomp(char *s, int n) int i; for(i = 0; i <= fpmax; i++) - if(fnames[i] && strncmp(s, fnames[i]->name, n) == 0 && fnames[i]->name[n] == 0) + if(fnames[i] && strncmp(s, fnames[i]->name, n) == 0) return i; return -1; } + /* * Encode a char file name as a sequence of short indices * into the file name dictionary. @@ -900,12 +919,13 @@ encfname(char *file) dest[i] = 0; return dest; } + /* * Search a history stack for a matching file name accumulating * the size of intervening files in the stack. */ static int -hline(File *fp, short *name, ulong *line) +hline(File *fp, short *name, long *line) { Hist *hp; int offset, depth; @@ -949,6 +969,7 @@ hline(File *fp, short *name, ulong *line) *line = ln+offset; return 1; } + /* * compare two encoded file names */ @@ -973,42 +994,19 @@ hcomp(Hist *hp, short *sp) } return *s == 0; } + /* * Convert a pc to a "file:line {file:line}" string. */ -int -fileline(char *str, int n, ulong dot) +long +fileline(char *str, int n, uvlong dot) { - long line; + long line, top, bot, mid; File *f; - int i; *str = 0; if(buildtbls() == 0) return 0; - - i = pc2filex(dot); - if (i >= 0) - { - f = &files[i]; - line = pc2line(dot); - if(line >= 0 && fline(str, n, line, f->hist, 0) >= 0) - return 1; - } - return 0; -} -/* - * Convert a pc to an index to the file table - */ -static int -pc2filex(ulong dot) -{ - int top, bot, mid; - File *f; - - if(buildtbls() == 0) - return -1; - /* binary search assumes file list is sorted by addr */ bot = 0; top = nfiles; @@ -1018,10 +1016,14 @@ pc2filex(ulong dot) top = mid; else if(mid < nfiles-1 && dot >= (f+1)->addr) bot = mid; - else - return mid; + else { + line = pc2line(dot); + if(line > 0 && fline(str, n, line, f->hist, 0) >= 0) + return 1; + break; + } } - return -1; + return 0; } /* @@ -1034,7 +1036,7 @@ fline(char *str, int n, long line, Hist *base, Hist **ret) { Hist *start; /* start of current level */ Hist *h; /* current entry */ - int delta; /* sum of size of files this level */ + long delta; /* sum of size of files this level */ int k; start = base; @@ -1056,9 +1058,8 @@ fline(char *str, int n, long line, Hist *base, Hist **ret) } } } else { - if(start == base) { /* end of recursion level */ - if(ret) - *ret = h; + if(start == base && ret) { /* end of recursion level */ + *ret = h; return 1; } else { /* end of included file */ delta += h->line-start->line; @@ -1094,6 +1095,7 @@ fline(char *str, int n, long line, Hist *base, Hist **ret) ********************/ return 0; } + /* * convert an encoded file name to a string. */ @@ -1113,16 +1115,28 @@ fileelem(Sym **fp, uchar *cp, char *buf, int n) *bp++ = *c++; } *bp = 0; - return bp-buf; + i = bp-buf; + if(i > 1) { + cleanname(buf); + i = strlen(buf); + } + return i; } + /* * compare the values of two symbol table entries. */ static int symcomp(void *a, void *b) { - return (*(Sym**)a)->value - (*(Sym**)b)->value; + int i; + + i = (*(Sym**)a)->value - (*(Sym**)b)->value; + if (i) + return i; + return strcmp((*(Sym**)a)->name, (*(Sym**)b)->name); } + /* * compare the values of the symbols referenced by two text table entries */ @@ -1131,6 +1145,7 @@ txtcomp(void *a, void *b) { return ((Txtsym*)a)->sym->value - ((Txtsym*)b)->sym->value; } + /* * compare the values of the symbols referenced by two file table entries */ @@ -1139,6 +1154,7 @@ filecomp(void *a, void *b) { return ((File*)a)->addr - ((File*)b)->addr; } + /* * fill an interface Symbol structure from a symbol table entry */ @@ -1148,6 +1164,7 @@ fillsym(Sym *sp, Symbol *s) s->type = sp->type; s->value = sp->value; s->name = sp->name; + s->index = 0; switch(sp->type) { case 'b': case 'B': @@ -1176,24 +1193,23 @@ fillsym(Sym *sp, Symbol *s) } s->handle = 0; } + /* * find the stack frame, given the pc */ -long -pc2sp(ulong pc) +uvlong +pc2sp(uvlong pc) { - uchar *c; - uchar u; - ulong currpc; - long currsp; + uchar *c, u; + uvlong currpc, currsp; if(spoff == 0) - return -1; + return ~0; currsp = 0; currpc = txtstart - mach->pcquant; if(pc<currpc || pc>txtend) - return -1; + return ~0; for(c = spoff; c < spoffend; c++) { if (currpc >= pc) return currsp; @@ -1210,76 +1226,29 @@ pc2sp(ulong pc) currpc += mach->pcquant*(u-129); currpc += mach->pcquant; } - return -1; + return ~0; } + /* * find the source file line number for a given value of the pc */ long -pc2line(ulong pc) -{ - File *fp; - return pc2fline(pc, &fp); -} -/* - * Convert a pc into a file table pointer & line offset - */ -static long -pc2fline(ulong pc, File **fpp) +pc2line(uvlong pc) { - File *f; - int i; - - i = pc2filex(pc); - if (i < 0) - return i; - if (i >= npcl){ - /* Precompute starting points by file, else too slow */ - if (npcl == 0){ - Pcl pcl; - - /* decode start for pcline machine */ - pcl.pcline = pcline; - pcl.pc = txtstart - mach->pcquant; - pcl.line = 0; - pcl2line(files->addr, &pcl, &files[0].pcl); - npcl = 1; - } - for (f = &files[npcl]; npcl <= i; npcl++, f++) - if (pcl2line(f->addr, &(f-1)->pcl, &f->pcl) < 0) - break; - } - f = &files[i]; - *fpp = f; - return pcl2line(pc, &f->pcl, 0); -} -/* - * Convert pc to line offset, given Pcl starting point, - * saving Pcl result. - */ -static long -pcl2line(ulong pc, Pcl *bp, Pcl *rp) -{ - uchar *c; - uchar u; - ulong currpc; + uchar *c, u; + uvlong currpc; long currline; - if(bp->pcline == 0) + if(pcline == 0) return -1; - currpc = bp->pc; - currline = bp->line; + currline = 0; + currpc = txtstart-mach->pcquant; if(pc<currpc || pc>txtend) - return -1; - for(c = bp->pcline; c < pclineend; c++) { - if (currpc >= pc) { - if (rp){ - rp->pc = currpc; - rp->line = currline; - rp->pcline = c; - } + return ~0; + + for(c = pcline; c < pclineend; c++) { + if(currpc >= pc) return currline; - } u = *c; if(u == 0) { currline += (c[1]<<24)|(c[2]<<16)|(c[3]<<8)|c[4]; @@ -1293,8 +1262,9 @@ pcl2line(ulong pc, Pcl *bp, Pcl *rp) currpc += mach->pcquant*(u-129); currpc += mach->pcquant; } - return -1; + return ~0; } + /* * find the pc associated with a line number * basepc and endpc are text addresses bounding the search. @@ -1302,22 +1272,21 @@ pcl2line(ulong pc, Pcl *bp, Pcl *rp) * usually, basepc and endpc contain the first text address in * a file and the first text address in the following file, respectively. */ -long -line2addr(ulong line, ulong basepc, ulong endpc) +uvlong +line2addr(long line, uvlong basepc, uvlong endpc) { - uchar *c; - uchar u; - ulong currpc; + uchar *c, u; + uvlong currpc, pc; long currline; long delta, d; - long pc, found; + int found; if(pcline == 0 || line == 0) - return -1; + return ~0; currline = 0; currpc = txtstart-mach->pcquant; - pc = -1; + pc = ~0; found = 0; delta = HUGEINT; @@ -1350,8 +1319,9 @@ line2addr(ulong line, ulong basepc, ulong endpc) } if(found) return pc; - return -1; + return ~0; } + /* * Print a history stack (debug). if count is 0, prints the whole stack */ @@ -1366,15 +1336,15 @@ printhist(char *msg, Hist *hp, int count) while(hp->name) { if(count && ++i > count) break; - fprint(2,"%s Line: %lx (%ld) Offset: %lx (%ld) Name: ", msg, + print("%s Line: %lx (%ld) Offset: %lx (%ld) Name: ", msg, hp->line, hp->line, hp->offset, hp->offset); for(cp = (uchar *)hp->name+1; (*cp<<8)|cp[1]; cp += 2) { if (cp != (uchar *)hp->name+1) - fprint(2,"/"); - fprint(2,"%x", (*cp<<8)|cp[1]); + print("/"); + print("%x", (*cp<<8)|cp[1]); } fileelem(fnames, (uchar *) hp->name, buf, sizeof(buf)); - fprint(2," (%s)\n", buf); + print(" (%s)\n", buf); hp++; } } diff --git a/utils/libmach/t.c b/utils/libmach/t.c index adea089b..809168e0 100644 --- a/utils/libmach/t.c +++ b/utils/libmach/t.c @@ -56,6 +56,7 @@ Mach mthumb = 0x1000, /* page size */ 0x80000000, /* kernel base */ 0, /* kernel text mask */ + 0x7FFFFFFF, /* stack top */ 2, /* quantization of pc */ 4, /* szaddr */ 4, /* szreg */ @@ -99,9 +100,9 @@ thumbpctab(Biobuf *b, Fhdr *fp) } int -thumbpclookup(ulong pc) +thumbpclookup(uvlong pc) { - ulong l, u, m; + uvlong l, u, m; pcentry *tab = pctab; l = 0; @@ -115,8 +116,7 @@ thumbpclookup(ulong pc) else l = u = m; } - if(l == u && u >= 0 && u < npctab && tab[u].start <= pc && pc <= tab[u].stop) + if(l == u && u < npctab && tab[u].start <= pc && pc <= tab[u].stop) return 1; // thumb return 0; // arm } - diff --git a/utils/libmach/tdb.c b/utils/libmach/tdb.c index 8eddc43a..8838d852 100644 --- a/utils/libmach/tdb.c +++ b/utils/libmach/tdb.c @@ -28,7 +28,7 @@ struct Opcode { char* o; void (*fmt)(Opcode*, Instr*); - ulong (*foll)(Map*, Rgetter, Instr*, ulong); + uvlong (*foll)(Map*, Rgetter, Instr*, uvlong); char* a; }; @@ -40,10 +40,10 @@ static char FRAMENAME[] = ".frame"; */ static char *thumbexcep(Map*, Rgetter); -static int thumbfoll(Map*, ulong, Rgetter, ulong*); -static int thumbinst(Map*, ulong, char, char*, int); -static int thumbdas(Map*, ulong, char*, int); -static int thumbinstlen(Map*, ulong); +static int thumbfoll(Map*, uvlong, Rgetter, uvlong*); +static int thumbinst(Map*, uvlong, char, char*, int); +static int thumbdas(Map*, uvlong, char*, int); +static int thumbinstlen(Map*, uvlong); /* * Debugger interface @@ -191,7 +191,7 @@ thumbclass(long w) } static int -decode(Map *map, ulong pc, Instr *i) +decode(Map *map, uvlong pc, Instr *i) { ushort w; @@ -277,7 +277,7 @@ gsymoff(char *buf, int n, long v, int space) if (!delta) return snprint(buf, n, "%s", s.name); if (s.type != 't' && s.type != 'T') - return snprint(buf, n, "%s+%lux", s.name, v-s.value); + return snprint(buf, n, "%s+%llux", s.name, v-s.value); else return snprint(buf, n, "#%lux", v); } @@ -318,8 +318,8 @@ thumbcondpass(Map *map, Rgetter rget, uchar cond) return 0; } -static ulong -thumbfbranch(Map *map, Rgetter rget, Instr *i, ulong pc) +static uvlong +thumbfbranch(Map *map, Rgetter rget, Instr *i, uvlong pc) { char buf[8]; @@ -346,8 +346,8 @@ thumbfbranch(Map *map, Rgetter rget, Instr *i, ulong pc) return 0; } -static ulong -thumbfmov(Map *map, Rgetter rget, Instr *i, ulong pc) +static uvlong +thumbfmov(Map *map, Rgetter rget, Instr *i, uvlong pc) { char buf[8]; ulong rd; @@ -360,8 +360,8 @@ thumbfmov(Map *map, Rgetter rget, Instr *i, ulong pc) return rget(map, buf); } -static ulong -thumbfadd(Map *map, Rgetter rget, Instr *i, ulong pc) +static uvlong +thumbfadd(Map *map, Rgetter rget, Instr *i, uvlong pc) { char buf[8]; ulong rd, v; @@ -712,7 +712,7 @@ format(char *mnemonic, Instr *i, char *f) fmt = "#%lx(R%d)"; if (i->rn == 15) { /* convert load of offset(PC) to a load immediate */ - if (get4(i->map, i->addr + i->imm, &i->imm) > 0) + if (get4(i->map, i->addr + i->imm, (ulong*)&i->imm) > 0) { g = 1; fmt = ""; @@ -773,7 +773,7 @@ format(char *mnemonic, Instr *i, char *f) } static int -printins(Map *map, ulong pc, char *buf, int n) +printins(Map *map, uvlong pc, char *buf, int n) { Instr i; @@ -787,14 +787,14 @@ printins(Map *map, ulong pc, char *buf, int n) } static int -thumbinst(Map *map, ulong pc, char modifier, char *buf, int n) +thumbinst(Map *map, uvlong pc, char modifier, char *buf, int n) { USED(modifier); return printins(map, pc, buf, n); } static int -thumbdas(Map *map, ulong pc, char *buf, int n) +thumbdas(Map *map, uvlong pc, char *buf, int n) { Instr i; @@ -809,7 +809,7 @@ thumbdas(Map *map, ulong pc, char *buf, int n) } static int -thumbinstlen(Map *map, ulong pc) +thumbinstlen(Map *map, uvlong pc) { Instr i; @@ -819,7 +819,7 @@ thumbinstlen(Map *map, ulong pc) } static int -thumbfoll(Map *map, ulong pc, Rgetter rget, ulong *foll) +thumbfoll(Map *map, uvlong pc, Rgetter rget, uvlong *foll) { ulong d; Instr i; diff --git a/utils/libmach/ureg6.h b/utils/libmach/ureg6.h index 46fa1f61..6e58d250 100644 --- a/utils/libmach/ureg6.h +++ b/utils/libmach/ureg6.h @@ -1,30 +1,30 @@ -struct Ureg -{ - uvlong r15; /* general registers */ - uvlong r14; - uvlong r13; - uvlong r12; - uvlong r11; - uvlong r10; - uvlong r9; - uvlong r8; - uvlong di; - uvlong si; /* ... */ - uvlong bp; /* ... */ - uvlong nsp; - uvlong bx; /* ... */ - uvlong dx; /* ... */ - uvlong cx; /* ... */ - uvlong ax; /* ... */ - uvlong gs; /* data segments */ - uvlong fs; /* ... */ - uvlong es; /* ... */ - uvlong ds; /* ... */ - uvlong trap; /* trap type */ - uvlong ecode; /* error code (or zero) */ - uvlong pc; /* pc */ - uvlong cs; /* old context */ - uvlong flags; /* old flags */ - uvlong sp; - uvlong ss; /* old stack segment */ +struct Ureg { + u64int ax; + u64int bx; + u64int cx; + u64int dx; + u64int si; + u64int di; + u64int bp; + u64int r8; + u64int r9; + u64int r10; + u64int r11; + u64int r12; + u64int r13; + u64int r14; + u64int r15; + + u16int ds; + u16int es; + u16int fs; + u16int gs; + + u64int type; + u64int error; /* error code (or zero) */ + u64int ip; /* pc */ + u64int cs; /* old context */ + u64int flags; /* old flags */ + u64int sp; /* sp */ + u64int ss; /* old stack segment */ }; diff --git a/utils/libmach/ureg9.h b/utils/libmach/ureg9.h new file mode 100644 index 00000000..676f5a57 --- /dev/null +++ b/utils/libmach/ureg9.h @@ -0,0 +1,44 @@ +struct Ureg +{ +/* 0*/ u64int cause; /* trap or interrupt vector */ +/* 8*/ u64int msr; /* SRR1 */ +/* 16*/ u64int pc; /* SRR0 */ +/* 24*/ u64int unused; +/* 32*/ u64int lr; +/* 36*/ u32int pad; +/* 40*/ u32int cr; +/* 48*/ u64int xer; +/* 56*/ u64int ctr; +/* 64*/ u64int r0; +/* 72*/ union{ u64int r1; u64int sp; u64int usp; }; +/* 80*/ u64int r2; +/* 88*/ u64int r3; +/* 96*/ u64int r4; +/*104*/ u64int r5; +/*112*/ u64int r6; +/*120*/ u64int r7; +/*128*/ u64int r8; +/*136*/ u64int r9; +/*144*/ u64int r10; +/*152*/ u64int r11; +/*160*/ u64int r12; +/*168*/ u64int r13; +/*176*/ u64int r14; +/*184*/ u64int r15; +/*192*/ u64int r16; +/*200*/ u64int r17; +/*208*/ u64int r18; +/*216*/ u64int r19; +/*224*/ u64int r20; +/*232*/ u64int r21; +/*240*/ u64int r22; +/*248*/ u64int r23; +/*256*/ u64int r24; +/*264*/ u64int r25; +/*272*/ u64int r26; +/*280*/ u64int r27; +/*288*/ u64int r28; +/*296*/ u64int r29; +/*304*/ u64int r30; +/*312*/ u64int r31; +}; diff --git a/utils/libmach/uregq.h b/utils/libmach/uregq.h index 409b13d3..d412b05a 100644 --- a/utils/libmach/uregq.h +++ b/utils/libmach/uregq.h @@ -1,7 +1,7 @@ struct Ureg { ulong cause; - ulong status; + ulong srr1; ulong pc; /* SRR0 */ ulong pad; ulong lr; diff --git a/utils/libmach/uregt.h b/utils/libmach/uregt.h index ffdad423..705a8675 100644 --- a/utils/libmach/uregt.h +++ b/utils/libmach/uregt.h @@ -1,21 +1,21 @@ struct Ureg { - uint r0; - uint r1; - uint r2; - uint r3; - uint r4; - uint r5; - uint r6; - uint r7; - uint r8; - uint r9; - uint r10; - uint r11; - uint r12; - uint r13; - uint r14; - uint link; - uint type; - uint psr; - uint pc; + u32int r0; + u32int r1; + u32int r2; + u32int r3; + u32int r4; + u32int r5; + u32int r6; + u32int r7; + u32int r8; + u32int r9; + u32int r10; + u32int r11; + u32int r12; + u32int r13; + u32int r14; + u32int link; + u32int type; + u32int psr; + u32int pc; }; diff --git a/utils/libmach/vcodas.c b/utils/libmach/vcodas.c index ce505ea2..b31fdb3e 100644 --- a/utils/libmach/vcodas.c +++ b/utils/libmach/vcodas.c @@ -5,7 +5,7 @@ /* mips native disassembler */ typedef struct { - long addr; /* pc of instr */ + uvlong addr; /* pc of instr */ uchar op; /* bits 31-26 */ uchar rs; /* bits 25-21 */ uchar rt; /* bits 20-16 */ @@ -281,9 +281,9 @@ static char fsub[16] = { static int -mkinstr(Instr *i, Map *map, ulong pc) +mkinstr(Instr *i, Map *map, uvlong pc) { - long w; + ulong w; if (get4(map, pc, &w) < 0) { werrstr("can't read instruction: %r"); @@ -305,6 +305,8 @@ mkinstr(Instr *i, Map *map, ulong pc) return 1; } +#pragma varargck argpos bprint 2 + static void bprint(Instr *i, char *fmt, ...) { @@ -505,7 +507,7 @@ cop0(Instr *i) } int -_mipscoinst(Map *map, ulong pc, char *buf, int n) +_mipscoinst(Map *map, uvlong pc, char *buf, int n) { Instr i; Opcode *o; diff --git a/utils/libmach/vdb.c b/utils/libmach/vdb.c index 0624a106..55798978 100644 --- a/utils/libmach/vdb.c +++ b/utils/libmach/vdb.c @@ -5,11 +5,12 @@ * Mips-specific debugger interface */ -extern char *mipsexcep(Map*, Rgetter); -extern int mipsfoll(Map*, ulong, Rgetter, ulong*); -extern int mipsinst(Map*, ulong, char, char*, int); -extern int mipsdas(Map*, ulong, char*, int); -extern int mipsinstlen(Map*, ulong); +static char *mipsexcep(Map*, Rgetter); +static int mipsfoll(Map*, uvlong, Rgetter, uvlong*); +static int mipsinst(Map*, uvlong, char, char*, int); +static int mipsdas(Map*, uvlong, char*, int); +static int mipsinstlen(Map*, uvlong); + /* * Debugger interface */ @@ -33,6 +34,73 @@ Machdata mipsmach = mipsinstlen, /* instruction size */ }; +Machdata mipsmachle = +{ + {0, 0, 0, 0xD}, /* break point */ + 4, /* break point size */ + + leswab, /* short to local byte order */ + leswal, /* long to local byte order */ + leswav, /* vlong to local byte order */ + risctrace, /* C traceback */ + riscframe, /* Frame finder */ + mipsexcep, /* print exception */ + 0, /* breakpoint fixup */ + leieeesftos, /* single precision float printer */ + leieeedftos, /* double precisioin float printer */ + mipsfoll, /* following addresses */ + mipsinst, /* print instruction */ + mipsdas, /* dissembler */ + mipsinstlen, /* instruction size */ +}; + +/* + * mips r4k little-endian + */ +Machdata mipsmach2le = +{ + {0, 0, 0, 0xD}, /* break point */ + 4, /* break point size */ + + leswab, /* short to local byte order */ + leswal, /* long to local byte order */ + leswav, /* vlong to local byte order */ + risctrace, /* C traceback */ + riscframe, /* Frame finder */ + mipsexcep, /* print exception */ + 0, /* breakpoint fixup */ + leieeesftos, /* single precision float printer */ + leieeedftos, /* double precisioin float printer */ + mipsfoll, /* following addresses */ + mipsinst, /* print instruction */ + mipsdas, /* dissembler */ + mipsinstlen, /* instruction size */ +}; + +/* + * mips r4k big-endian + */ +Machdata mipsmach2be = +{ + {0, 0, 0, 0xD}, /* break point */ + 4, /* break point size */ + + beswab, /* short to local byte order */ + beswal, /* long to local byte order */ + beswav, /* vlong to local byte order */ + risctrace, /* C traceback */ + riscframe, /* Frame finder */ + mipsexcep, /* print exception */ + 0, /* breakpoint fixup */ + beieeesftos, /* single precision float printer */ + beieeedftos, /* double precisioin float printer */ + mipsfoll, /* following addresses */ + mipsinst, /* print instruction */ + mipsdas, /* dissembler */ + mipsinstlen, /* instruction size */ +}; + + static char *excname[] = { "external interrupt", @@ -55,7 +123,7 @@ static char *excname[] = "floating point exception" /* FPEXC */ }; -char* +static char* mipsexcep(Map *map, Rgetter rget) { int e; @@ -74,7 +142,7 @@ mipsexcep(Map *map, Rgetter rget) static char FRAMENAME[] = ".frame"; typedef struct { - ulong addr; + uvlong addr; uchar op; /* bits 31-26 */ uchar rs; /* bits 25-21 */ uchar rt; /* bits 20-16 */ @@ -95,14 +163,15 @@ typedef struct { static Map *mymap; static int -decode(ulong pc, Instr *i) +decode(uvlong pc, Instr *i) { - long w; + ulong w; if (get4(mymap, pc, &w) < 0) { werrstr("can't read instruction: %r"); return -1; } + i->addr = pc; i->size = 1; i->op = (w >> 26) & 0x3F; @@ -121,7 +190,7 @@ decode(ulong pc, Instr *i) } static int -mkinstr(ulong pc, Instr *i) +mkinstr(uvlong pc, Instr *i) { Instr x; @@ -173,6 +242,8 @@ mkinstr(ulong pc, Instr *i) return 1; } +#pragma varargck argpos bprint 2 + static void bprint(Instr *i, char *fmt, ...) { @@ -942,7 +1013,7 @@ cop1(Instr *i) } static int -printins(Map *map, ulong pc, char *buf, int n) +printins(Map *map, uvlong pc, char *buf, int n) { Instr i; Opcode *o; @@ -995,11 +1066,11 @@ printins(Map *map, ulong pc, char *buf, int n) return i.size*4; } -extern int _mipscoinst(Map *, ulong, char*, int); +extern int _mipscoinst(Map *, uvlong, char*, int); /* modifier 'I' toggles the default disassembler type */ -int -mipsinst(Map *map, ulong pc, char modifier, char *buf, int n) +static int +mipsinst(Map *map, uvlong pc, char modifier, char *buf, int n) { if ((asstype == AMIPSCO && modifier == 'i') || (asstype == AMIPS && modifier == 'I')) @@ -1008,8 +1079,8 @@ mipsinst(Map *map, ulong pc, char modifier, char *buf, int n) return printins(map, pc, buf, n); } -int -mipsdas(Map *map, ulong pc, char *buf, int n) +static int +mipsdas(Map *map, uvlong pc, char *buf, int n) { Instr i; @@ -1028,8 +1099,8 @@ mipsdas(Map *map, ulong pc, char *buf, int n) return i.size*4; } -int -mipsinstlen(Map *map, ulong pc) +static int +mipsinstlen(Map *map, uvlong pc) { Instr i; @@ -1039,8 +1110,8 @@ mipsinstlen(Map *map, ulong pc) return i.size*4; } -int -mipsfoll(Map *map, ulong pc, Rgetter rget, ulong *foll) +static int +mipsfoll(Map *map, uvlong pc, Rgetter rget, uvlong *foll) { ulong w, l; char buf[8]; diff --git a/utils/qa/a.y b/utils/qa/a.y index 3474ea0d..ee425949 100644 --- a/utils/qa/a.y +++ b/utils/qa/a.y @@ -20,9 +20,9 @@ %token <lval> LNOP LEND LRETT LWORD LTEXT LDATA LRETRN %token <lval> LCONST LSP LSB LFP LPC LCREG LFLUSH %token <lval> LREG LFREG LR LCR LF LFPSCR -%token <lval> LLR LCTR LSPR LSPREG LSEG LMSR +%token <lval> LLR LCTR LSPR LSPREG LSEG LMSR LDCR %token <lval> LSCHED LXLD LXST LXOP LXMV -%token <lval> LRLWM LMOVMW LMOVEM LMOVFL LMTFSB LMA +%token <lval> LRLWM LMOVMW LMOVEM LMOVFL LMTFSB LMA LFMOVX %token <dval> LFCONST %token <sval> LSCONST %token <sym> LNAME LLAB LVAR @@ -95,7 +95,7 @@ inst: outcode($1, &$2, NREG, &$4); } /* - * load floats + * load and store floats */ | LFMOV addr ',' freg { @@ -122,6 +122,17 @@ inst: outcode($1, &$2, NREG, &$4); } /* + * load and store floats, indexed only + */ +| LFMOVX regaddr ',' freg + { + outcode($1, &$2, NREG, &$4); + } +| LFMOVX freg ',' regaddr + { + outcode($1, &$2, NREG, &$4); + } +/* * store ints and bytes */ | LMOVW rreg ',' addr @@ -697,6 +708,19 @@ psr: $$.type = $1; $$.offset = $3; } +| LDCR '(' con ')' + { + $$ = nullgen; + $$.type = $1; + $$.offset = $3; + } +| LDCR '(' sreg ')' + { + $$ = nullgen; + $$.type = $1; + $$.reg = $3; + $$.offset = 0; + } | msr seg: diff --git a/utils/qa/lex.c b/utils/qa/lex.c index e711a5c6..5f1dd202 100644 --- a/utils/qa/lex.c +++ b/utils/qa/lex.c @@ -169,7 +169,7 @@ struct "MSR", LMSR, D_MSR, "FPSCR", LFPSCR, D_FPSCR, "SPR", LSPR, D_SPR, - "DCR", LSPR, D_DCR, + "DCR", LDCR, D_DCR, "SEG", LSEG, D_SREG, @@ -539,7 +539,85 @@ struct "NMACLHWV", LMA, ANMACLHWV, "NMACLHWVCC", LMA, ANMACLHWVCC, -/* special instructions */ + /* optional on 32-bit */ + "FRES", LFCONV, AFRES, + "FRESCC", LFCONV, AFRESCC, + "FRSQRTE", LFCONV, AFRSQRTE, + "FRSQRTECC", LFCONV, AFRSQRTECC, + "FSEL", LFMA, AFSEL, + "FSELCC", LFMA, AFSELCC, + "FSQRT", LFCONV, AFSQRT, + "FSQRTCC", LFCONV, AFSQRTCC, + "FSQRTS", LFCONV, AFSQRTS, + "FSQRTSCC", LFCONV, AFSQRTSCC, + + /* parallel, cross, and secondary (fp2) */ + "FPSEL", LFMA, AFPSEL, + "FPMUL", LFADD, AFPMUL, + "FXMUL", LFADD, AFXMUL, + "FXPMUL", LFADD, AFXPMUL, + "FXSMUL", LFADD, AFXSMUL, + "FPADD", LFADD, AFPADD, + "FPSUB", LFADD, AFPSUB, + "FPRE", LFCONV, AFPRE, + "FPRSQRTE", LFCONV, AFPRSQRTE, + "FPMADD", LFMA, AFPMADD, + "FXMADD", LFMA, AFXMADD, + "FXCPMADD", LFMA, AFXCPMADD, + "FXCSMADD", LFMA, AFXCSMADD, + "FPNMADD", LFMA, AFPNMADD, + "FXNMADD", LFMA, AFXNMADD, + "FXCPNMADD", LFMA, AFXCPNMADD, + "FXCSNMADD", LFMA, AFXCSNMADD, + "FPMSUB", LFMA, AFPMSUB, + "FXMSUB", LFMA, AFXMSUB, + "FXCPMSUB", LFMA, AFXCPMSUB, + "FXCSMSUB", LFMA, AFXCSMSUB, + "FPNMSUB", LFMA, AFPNMSUB, + "FXNMSUB", LFMA, AFXNMSUB, + "FXCPNMSUB", LFMA, AFXCPNMSUB, + "FXCSNMSUB", LFMA, AFXCSNMSUB, + "FPABS", LFCONV, AFPABS, + "FPNEG", LFCONV, AFPNEG, + "FPRSP", LFCONV, AFPRSP, + "FPNABS", LFCONV, AFPNABS, + "FSMOVD", LFMOV, AFSMOVD, + "FSCMP", LFCMP, AFSCMP, + "FSABS", LFCONV, AFSABS, + "FSNEG", LFCONV, AFSNEG, + "FSNABS", LFCONV, AFSNABS, + "FPCTIW", LFCONV, AFPCTIW, + "FPCTIWZ", LFCONV, AFPCTIWZ, + "FMOVSPD", LFCONV, AFMOVSPD, + "FMOVPSD", LFCONV, AFMOVPSD, + "FXCPNPMA", LFMA, AFXCPNPMA, + "FXCSNPMA", LFMA, AFXCSNPMA, + "FXCPNSMA", LFMA, AFXCPNSMA, + "FXCSNSMA", LFMA, AFXCSNSMA, + "FXCXNPMA", LFMA, AFXCXNPMA, + "FXCXNSMA", LFMA, AFXCXNSMA, + "FXCXMA", LFMA, AFXCXMA, + "FXCXNMS", LFMA, AFXCXNMS, + + /* parallel, cross, and secondary load and store (fp2) */ + "FSMOVS", LFMOVX, AFSMOVS, + "FSMOVSU", LFMOVX, AFSMOVSU, + "FSMOVD", LFMOVX, AFSMOVD, + "FSMOVDU", LFMOVX, AFSMOVDU, + "FXMOVS", LFMOVX, AFXMOVS, + "FXMOVSU", LFMOVX, AFXMOVSU, + "FXMOVD", LFMOVX, AFXMOVD, + "FXMOVDU", LFMOVX, AFXMOVDU, + "FPMOVS", LFMOVX, AFPMOVS, + "FPMOVSU", LFMOVX, AFPMOVSU, + "FPMOVD", LFMOVX, AFPMOVD, + "FPMOVDU", LFMOVX, AFPMOVDU, + "FPMOVIW", LFMOVX, AFPMOVIW, + + "AFMOVSPD", LFMOV, AFMOVSPD, + "AFMOVPSD", LFMOV, AFMOVPSD, + + /* special instructions */ "DCBF", LXOP, ADCBF, "DCBI", LXOP, ADCBI, "DCBST", LXOP, ADCBST, @@ -626,6 +704,7 @@ zname(char *n, int t, int s) { Bputc(&obuf, ANAME); + Bputc(&obuf, ANAME>>8); Bputc(&obuf, t); /* type */ Bputc(&obuf, s); /* sym */ while(*n) { @@ -746,6 +825,7 @@ outcode(int a, Gen *g1, int reg, Gen *g2) st = outsim(g2); } while(sf != 0 && st == sf); Bputc(&obuf, a); + Bputc(&obuf, a>>8); Bputc(&obuf, reg|nosched); Bputc(&obuf, lineno); Bputc(&obuf, lineno>>8); @@ -773,6 +853,7 @@ outgcode(int a, Gen *g1, int reg, Gen *g2, Gen *g3) if(g2->type != D_NONE) flag = 0x40; /* flags extra operand */ Bputc(&obuf, a); + Bputc(&obuf, a>>8); Bputc(&obuf, reg | nosched | flag); Bputc(&obuf, lineno); Bputc(&obuf, lineno>>8); @@ -828,6 +909,7 @@ outhist(void) } if(n) { Bputc(&obuf, ANAME); + Bputc(&obuf, ANAME>>8); Bputc(&obuf, D_FILE); /* type */ Bputc(&obuf, 1); /* sym */ Bputc(&obuf, '<'); @@ -843,6 +925,7 @@ outhist(void) g.offset = h->offset; Bputc(&obuf, AHISTORY); + Bputc(&obuf, AHISTORY>>8); Bputc(&obuf, 0); Bputc(&obuf, h->line); Bputc(&obuf, h->line>>8); diff --git a/utils/qc/cgen.c b/utils/qc/cgen.c index 8323466c..d26704de 100644 --- a/utils/qc/cgen.c +++ b/utils/qc/cgen.c @@ -1,5 +1,10 @@ #include "gc.h" +static void cmpv(Node*, int, Node*); +static void testv(Node*, int); +static void cgen64(Node*, Node*); +static int isvconstable(int, vlong); + void cgen(Node *n, Node *nn) { @@ -15,10 +20,18 @@ cgen(Node *n, Node *nn) } if(n == Z || n->type == T) return; - if(typesuv[n->type->etype]) { + if(typesu[n->type->etype]) { sugen(n, nn, n->type->width); return; } + if(typev[n->type->etype]) { + switch(n->op) { + case OCONST: + case OFUNC: + cgen64(n, nn); + return; + } + } l = n->left; r = n->right; o = n->op; @@ -44,13 +57,17 @@ cgen(Node *n, Node *nn) if(r != Z && r->complex >= FNX) switch(o) { default: - regret(&nod, r); - cgen(r, &nod); - - regsalloc(&nod1, r); - gopcode(OAS, &nod, Z, &nod1); + if(!typev[r->type->etype]) { + regret(&nod, r); + cgen(r, &nod); + regsalloc(&nod1, r); + gmove(&nod, &nod1); + regfree(&nod); + } else { + regsalloc(&nod1, r); + cgen(r, &nod1); + } - regfree(&nod); nod = *n; nod.right = &nod1; cgen(&nod, nn); @@ -70,6 +87,19 @@ cgen(Node *n, Node *nn) diag(n, "unknown op in cgen: %O", o); break; + case ONEG: + case OCOM: + if(nn == Z) { + nullwarn(l, Z); + break; + } + regalloc(&nod, l, nn); + cgen(l, &nod); + gopcode(o, &nod, Z, &nod); + gmove(&nod, nn); + regfree(&nod); + break; + case OAS: if(l->op == OBIT) goto bitas; @@ -132,8 +162,11 @@ cgen(Node *n, Node *nn) case OXOR: if(nn != Z) if(r->op == OCONST && r->vconst == -1){ - cgen(l, nn); - gopcode(OCOM, nn, Z, nn); + regalloc(&nod, l, nn); + cgen(l, &nod); + gopcode(OCOM, &nod, Z, &nod); + gmove(&nod, nn); + regfree(&nod); break; } @@ -147,15 +180,14 @@ cgen(Node *n, Node *nn) /* * immediate operands */ - if(nn != Z) - if(r->op == OCONST) - if(!typefd[n->type->etype]) { - cgen(l, nn); - if(r->vconst == 0) - if(o != OAND) - break; - if(nn != Z) - gopcode(o, r, Z, nn); + if(nn != Z && r->op == OCONST && !typefd[n->type->etype] && + (!typev[n->type->etype] || isvconstable(o, r->vconst))) { + regalloc(&nod, l, nn); + cgen(l, &nod); + if(o == OAND || r->vconst != 0) + gopcode(o, r, Z, &nod); + gmove(&nod, nn); + regfree(&nod); break; } @@ -169,7 +201,7 @@ cgen(Node *n, Node *nn) nullwarn(l, r); break; } - if(o == OMUL || o == OLMUL) { + if((o == OMUL || o == OLMUL) && !typev[n->type->etype]) { if(mulcon(n, nn)) break; if(debug['M']) @@ -178,19 +210,23 @@ cgen(Node *n, Node *nn) if(l->complex >= r->complex) { regalloc(&nod, l, nn); cgen(l, &nod); - regalloc(&nod1, r, Z); + if(o != OMUL || typev[n->type->etype] || !sconst(r)) { + regalloc(&nod1, r, Z); + cgen(r, &nod1); + gopcode(o, &nod1, Z, &nod); + regfree(&nod1); + } else + gopcode(o, r, Z, &nod); + } else { + regalloc(&nod1, r, nn); cgen(r, &nod1); + regalloc(&nod, l, Z); + cgen(l, &nod); gopcode(o, &nod1, Z, &nod); - } else { - regalloc(&nod, r, nn); - cgen(r, &nod); - regalloc(&nod1, l, Z); - cgen(l, &nod1); - gopcode(o, &nod, &nod1, &nod); + regfree(&nod1); } gopcode(OAS, &nod, Z, nn); regfree(&nod); - regfree(&nod1); break; case OASLSHR: @@ -203,14 +239,13 @@ cgen(Node *n, Node *nn) case OASOR: if(l->op == OBIT) goto asbitop; - if(r->op == OCONST) - if(!typefd[r->type->etype]) - if(!typefd[n->type->etype]) { + if(r->op == OCONST && !typefd[r->type->etype] && !typefd[n->type->etype] && + (!typev[n->type->etype] || isvconstable(o, r->vconst))) { if(l->addable < INDEXED) reglcgen(&nod2, l, Z); else nod2 = *l; - regalloc(&nod, r, nn); + regalloc(&nod, l, nn); gopcode(OAS, &nod2, Z, &nod); gopcode(o, r, Z, &nod); gopcode(OAS, &nod, Z, &nod2); @@ -234,20 +269,22 @@ cgen(Node *n, Node *nn) reglcgen(&nod2, l, Z); else nod2 = *l; - regalloc(&nod, n, nn); + regalloc(&nod, r, Z); cgen(r, &nod); } else { - regalloc(&nod, n, nn); + regalloc(&nod, r, Z); cgen(r, &nod); if(l->addable < INDEXED) reglcgen(&nod2, l, Z); else nod2 = *l; } - regalloc(&nod1, n, Z); + regalloc(&nod1, n, nn); gopcode(OAS, &nod2, Z, &nod1); - gopcode(o, &nod, &nod1, &nod); - gopcode(OAS, &nod, Z, &nod2); + gopcode(o, &nod, Z, &nod1); + gopcode(OAS, &nod1, Z, &nod2); + if(nn != Z) + gopcode(OAS, &nod1, Z, nn); regfree(&nod); regfree(&nod1); if(l->addable < INDEXED) @@ -336,7 +373,7 @@ cgen(Node *n, Node *nn) } else cgen(l, &nod); regind(&nod, n); - gopcode(OAS, &nod, Z, nn); + gmove(&nod, nn); regfree(&nod); break; @@ -390,11 +427,15 @@ cgen(Node *n, Node *nn) cgen(l, nn); break; } + if(typev[l->type->etype] || typev[n->type->etype]) { + cgen64(n, nn); + break; + } regalloc(&nod, l, nn); cgen(l, &nod); regalloc(&nod1, n, &nod); - gopcode(OAS, &nod, Z, &nod1); - gopcode(OAS, &nod1, Z, nn); + gmove(&nod, &nod1); + gmove(&nod1, nn); regfree(&nod1); regfree(&nod); break; @@ -496,6 +537,8 @@ cgen(Node *n, Node *nn) } else gopcode(OADD, nodconst(v), Z, &nod); gopcode(OAS, &nod, Z, &nod2); + if(nn && l->op == ONAME) /* in x=++i, emit USED(i) */ + gins(ANOP, l, Z); regfree(&nod); if(l->addable < INDEXED) @@ -608,7 +651,7 @@ bcgen(Node *n, int true) void boolgen(Node *n, int true, Node *nn) { - int o; + int o, uns; Prog *p1, *p2; Node *l, *r, nod, nod1; long curs; @@ -617,6 +660,7 @@ boolgen(Node *n, int true, Node *nn) prtree(nn, "boolgen lhs"); prtree(n, "boolgen"); } + uns = 0; curs = cursafe; l = n->left; r = n->right; @@ -635,6 +679,10 @@ boolgen(Node *n, int true, Node *nn) } goto com; } + if(typev[n->type->etype]) { + testv(n, true); + goto com; + } regalloc(&nod, n, nn); cgen(n, &nod); o = ONE; @@ -701,16 +749,22 @@ boolgen(Node *n, int true, Node *nn) patch(p2, pc); goto com; + case OHI: + case OHS: + case OLO: + case OLS: + uns = 1; + /* fall through */ case OEQ: case ONE: case OLE: case OLT: case OGE: case OGT: - case OHI: - case OHS: - case OLO: - case OLS: + if(typev[l->type->etype]){ + cmpv(n, true, Z); + goto com; + } o = n->op; if(true) o = comrel[relindex(o)]; @@ -725,7 +779,7 @@ boolgen(Node *n, int true, Node *nn) boolgen(&nod, true, nn); break; } - if(sconst(r)) { + if(!uns && sconst(r) || (uns || o == OEQ || o == ONE) && uconst(r)) { regalloc(&nod, l, nn); cgen(l, &nod); gopcode(o, &nod, Z, r); @@ -773,13 +827,17 @@ sugen(Node *n, Node *nn, long w) if(n == Z || n->type == T) return; + if(nn == nodrat) + if(w > nrathole) + nrathole = w; if(debug['g']) { prtree(nn, "sugen lhs"); prtree(n, "sugen"); } - if(nn == nodrat) - if(w > nrathole) - nrathole = w; + if(typev[n->type->etype]) { + diag(n, "old vlong sugen: %O", n->op); + return; + } switch(n->op) { case OIND: if(nn == Z) { @@ -790,33 +848,6 @@ sugen(Node *n, Node *nn, long w) default: goto copy; - case OCONST: - if(n->type && typev[n->type->etype]) { - if(nn == Z) { - nullwarn(n->left, Z); - break; - } - - t = nn->type; - nn->type = types[TLONG]; - reglcgen(&nod1, nn, Z); - nn->type = t; - - if(align(0, types[TCHAR], Aarg1)) /* isbigendian */ - gopcode(OAS, nod32const(n->vconst>>32), Z, &nod1); - else - gopcode(OAS, nod32const(n->vconst), Z, &nod1); - nod1.xoffset += SZ_LONG; - if(align(0, types[TCHAR], Aarg1)) /* isbigendian */ - gopcode(OAS, nod32const(n->vconst), Z, &nod1); - else - gopcode(OAS, nod32const(n->vconst>>32), Z, &nod1); - - regfree(&nod1); - break; - } - goto copy; - case ODOT: l = n->left; sugen(l, nodrat, l->type->width); @@ -922,6 +953,7 @@ sugen(Node *n, Node *nn, long w) break; case OFUNC: + /* this transformation should probably be done earlier */ if(nn == Z) { sugen(n, nodrat, w); break; @@ -933,6 +965,7 @@ sugen(Node *n, Node *nn, long w) } else nn = nn->left; n = new(OFUNC, n->left, new(OLIST, nn, n->right)); + n->complex = FNX; n->type = types[TVOID]; n->left->type = types[TVOID]; cgen(n, Z); @@ -967,7 +1000,7 @@ copy: regsalloc(&nod2, nn); nn->type = t; - gopcode(OAS, &nod1, Z, &nod2); + gmove(&nod1, &nod2); regfree(&nod1); nod2.type = typ(TIND, t); @@ -1089,3 +1122,338 @@ layout(Node *f, Node *t, int c, int cv, Node *cn) regfree(&t1); regfree(&t2); } + +/* + * is the vlong's value directly addressible? + */ +int +isvdirect(Node *n) +{ + return n->op == ONAME || n->op == OCONST || n->op == OINDREG; +} + +/* + * can the constant be used with given vlong op? + */ +static int +isvconstable(int o, vlong v) +{ + switch(o) { + case OADD: + case OASADD: + /* there isn't an immediate form for ADDE/SUBE, but there are special ADDME/ADDZE etc */ + return v == 0 || v == -1; + case OAND: + case OOR: + case OXOR: + case OLSHR: + case OASHL: + case OASHR: + case OASLSHR: + case OASASHL: + case OASASHR: + return 1; + } + return 0; +} + +/* + * most 64-bit operations: cgen into a register pair, then operate. + * 64-bit comparisons are handled a little differently because the two underlying + * comparisons can be compiled separately, since the calculations don't interact. + */ + +static void +vcgen(Node *n, Node *o, int *f) +{ + *f = 0; + if(!isvdirect(n)) { + if(n->complex >= FNX) { + regsalloc(o, n); + cgen(n, o); + return; + } + *f = 1; + if(n->addable < INDEXED && n->op != OIND && n->op != OINDEX) { + regalloc(o, n, Z); + cgen(n, o); + } else + reglcgen(o, n, Z); + } else + *o = *n; +} + +static int +isuns(int op) +{ + switch(op){ + case OLO: + case OLS: + case OHI: + case OHS: + return 1; + default: + return 0; + } +} + +static void +gcmpv(Node *l, Node *r, void (*mov)(Node*, Node*, int), int op) +{ + Node vl, vr; + + regalloc(&vl, ®node, Z); + mov(l, &vl, 0); + regalloc(&vr, ®node, Z); + mov(r, &vr, 1+isuns(op)); + gopcode(op, &vl, Z, &vr); + if(vl.op == OREGISTER) + regfree(&vl); + if(vr.op == OREGISTER) + regfree(&vr); +} + +static void +brcondv(Node *l, Node *r, int chi, int clo) +{ + Prog *p1, *p2, *p3, *p4; + + gcmpv(l, r, gloadhi, chi); + p1 = p; + gins(ABNE, Z, Z); + p2 = p; + gcmpv(l, r, gloadlo, clo); + p3 = p; + gbranch(OGOTO); + p4 = p; + patch(p1, pc); + patch(p3, pc); + gbranch(OGOTO); + patch(p2, pc); + patch(p4, pc); +} + +static void +testv(Node *n, int true) +{ + Node nod; + + nod = znode; + nod.op = ONE; + nod.left = n; + nod.right = new1(0, Z, Z); + *nod.right = *nodconst(0); + nod.right->type = n->type; + nod.type = types[TLONG]; + cmpv(&nod, true, Z); +} + +/* + * comparison for vlong does high and low order parts separately, + * which saves loading the latter if the high order comparison suffices + */ +static void +cmpv(Node *n, int true, Node *nn) +{ + Node *l, *r, nod, nod1; + int o, f1, f2; + Prog *p1, *p2; + long curs; + + if(debug['g']) { + if(nn != nil) + prtree(nn, "cmpv lhs"); + prtree(n, "cmpv"); + } + curs = cursafe; + l = n->left; + r = n->right; + if(l->complex >= FNX && r->complex >= FNX) { + regsalloc(&nod1, r); + cgen(r, &nod1); + nod = *n; + nod.right = &nod1; + cmpv(&nod, true, nn); + cursafe = curs; + return; + } + if(l->complex >= r->complex) { + vcgen(l, &nod1, &f1); + vcgen(r, &nod, &f2); + } else { + vcgen(r, &nod, &f2); + vcgen(l, &nod1, &f1); + } + nod.type = types[TLONG]; + nod1.type = types[TLONG]; + o = n->op; + if(true) + o = comrel[relindex(o)]; + switch(o){ + case OEQ: + gcmpv(&nod1, &nod, gloadhi, ONE); + p1 = p; + gcmpv(&nod1, &nod, gloadlo, ONE); + p2 = p; + gbranch(OGOTO); + patch(p1, pc); + patch(p2, pc); + break; + case ONE: + gcmpv(&nod1, &nod, gloadhi, ONE); + p1 = p; + gcmpv(&nod1, &nod, gloadlo, OEQ); + p2 = p; + patch(p1, pc); + gbranch(OGOTO); + patch(p2, pc); + break; + case OLE: + brcondv(&nod1, &nod, OLT, OLS); + break; + case OGT: + brcondv(&nod1, &nod, OGT, OHI); + break; + case OLS: + brcondv(&nod1, &nod, OLO, OLS); + break; + case OHI: + brcondv(&nod1, &nod, OHI, OHI); + break; + case OLT: + brcondv(&nod1, &nod, OLT, OLO); + break; + case OGE: + brcondv(&nod1, &nod, OGT, OHS); + break; + case OLO: + brcondv(&nod1, &nod, OLO, OLO); + break; + case OHS: + brcondv(&nod1, &nod, OHI, OHS); + break; + default: + diag(n, "bad cmpv"); + return; + } + if(f1) + regfree(&nod1); + if(f2) + regfree(&nod); + cursafe = curs; +} + +static void +cgen64(Node *n, Node *nn) +{ + Node *l, *r, *d; + Node nod, nod1; + long curs; + Type *t; + int o, m; + + curs = cursafe; + l = n->left; + r = n->right; + o = n->op; + switch(o) { + + case OCONST: + if(nn == Z) { + nullwarn(n->left, Z); + break; + } + if(nn->op != OREGPAIR) { +//prtree(n, "cgen64 const"); + t = nn->type; + nn->type = types[TLONG]; + reglcgen(&nod1, nn, Z); + nn->type = t; + + if(align(0, types[TCHAR], Aarg1)) /* isbigendian */ + gmove(nod32const(n->vconst>>32), &nod1); + else + gmove(nod32const(n->vconst), &nod1); + nod1.xoffset += SZ_LONG; + if(align(0, types[TCHAR], Aarg1)) /* isbigendian */ + gmove(nod32const(n->vconst), &nod1); + else + gmove(nod32const(n->vconst>>32), &nod1); + + regfree(&nod1); + } else + gmove(n, nn); + break; + + case OCAST: + /* + * convert from types l->n->nn + */ + if(typev[l->type->etype]){ + /* vlong to non-vlong */ + if(!isvdirect(l)) { + if(l->addable < INDEXED && l->op != OIND && l->op != OINDEX) { + regalloc(&nod, l, l); + cgen(l, &nod); + regalloc(&nod1, n, nn); + gmove(nod.right, &nod1); + } else { + reglcgen(&nod, l, Z); + regalloc(&nod1, n, nn); + gloadlo(&nod, &nod1, 0); /* TO DO: not correct for typefd */ + } + regfree(&nod); + } else { + regalloc(&nod1, n, nn); + gloadlo(l, &nod1, 0); /* TO DO: not correct for typefd */ + } + }else{ + /* non-vlong to vlong */ + regalloc(&nod, l, Z); + cgen(l, &nod); + regalloc(&nod1, n, nn); + gmove(&nod, nod1.right); + if(typeu[l->type->etype]) + gmove(nodconst(0), nod1.left); + else + gopcode(OASHR, nodconst(31), nod1.right, nod1.left); + regfree(&nod); + } + gmove(&nod1, nn); + regfree(&nod1); + break; + + case OFUNC: + /* this transformation should probably be done earlier */ + if(nn == Z) { + regsalloc(&nod1, n); + nn = &nod1; + } + m = 0; + if(nn->op != OIND) { + if(nn->op == OREGPAIR) { + m = 1; + regsalloc(&nod1, nn); + d = &nod1; + }else + d = nn; + d = new1(OADDR, d, Z); + d->type = types[TIND]; + d->addable = 0; + } else + d = nn->left; + n = new(OFUNC, l, new(OLIST, d, r)); + n->complex = FNX; + n->type = types[TVOID]; + n->left->type = types[TVOID]; + cgen(n, Z); + if(m) + gmove(&nod1, nn); + break; + + default: + diag(n, "bad cgen64 %O", o); + break; + } + cursafe = curs; +} diff --git a/utils/qc/enam.c b/utils/qc/enam.c index 70535f8a..98d0edcf 100644 --- a/utils/qc/enam.c +++ b/utils/qc/enam.c @@ -130,21 +130,11 @@ char *anames[] = "MOVW", "MOVWU", "MOVFL", - "MOVCRFXXX", "MOVCRFS", - "MOVCRXRXXX", - "MOVFCRXXX", - "MFFSXXX", - "MFFSCCXXX", - "MTCRFXXX", "MTFSB0", "MTFSB0CC", "MTFSB1", "MTFSB1CC", - "MTFSFXXX", - "MTFSFCCXXX", - "MTFSFIXXX", - "MTFSFIXXXCC", "MULHW", "MULHWCC", "MULHWU", @@ -184,9 +174,7 @@ char *anames[] = "SRAW", "SRAWCC", "SRWCC", - "ILLXXX1", "STSW", - "STWBRXXX", "STWCCC", "SUB", "SUBCC", @@ -323,5 +311,76 @@ char *anames[] = "NMACLHWV", "NMACLHWVCC", "RFCI", + "FRES", + "FRESCC", + "FRSQRTE", + "FRSQRTECC", + "FSEL", + "FSELCC", + "FSQRT", + "FSQRTCC", + "FSQRTS", + "FSQRTSCC", + "FPSEL", + "FPMUL", + "FXMUL", + "FXPMUL", + "FXSMUL", + "FPADD", + "FPSUB", + "FPRE", + "FPRSQRTE", + "FPMADD", + "FXMADD", + "FXCPMADD", + "FXCSMADD", + "FPNMADD", + "FXNMADD", + "FXCPNMADD", + "FXCSNMADD", + "FPMSUB", + "FXMSUB", + "FXCPMSUB", + "FXCSMSUB", + "FPNMSUB", + "FXNMSUB", + "FXCPNMSUB", + "FXCSNMSUB", + "FPMOVD", + "FPABS", + "FPNEG", + "FPRSP", + "FPNABS", + "FSMOVD", + "FSCMP", + "FSABS", + "FSNEG", + "FSNABS", + "FXMOVD", + "FPCTIW", + "FPCTIWZ", + "FSMOVP", + "FPMOVS", + "FXCPNPMA", + "FXCSNPMA", + "FXCPNSMA", + "FXCSNSMA", + "FXCXNPMA", + "FXCXNSMA", + "FXCXMA", + "FXCXNMS", + "FMOVSS", + "FMOVSSU", + "FMOVSD", + "FMOVSDU", + "FMOVXS", + "FMOVSXU", + "FMOVXD", + "FMOVXDU", + "FMOVPS", + "FMOVPSU", + "FMOVPD", + "FMOVPDU", + "FMOVPIW", "LAST", }; diff --git a/utils/qc/gc.h b/utils/qc/gc.h index bf4e9091..16aab0ba 100644 --- a/utils/qc/gc.h +++ b/utils/qc/gc.h @@ -58,6 +58,7 @@ struct Case long val; long label; char def; + char isv; }; #define C ((Case*)0) @@ -129,6 +130,7 @@ struct Rgn }; EXTERN long breakpc; +EXTERN long nbreak; EXTERN Case* cases; EXTERN Node constnode; EXTERN Node fconstnode; @@ -141,10 +143,10 @@ EXTERN int hintabsize; EXTERN long maxargsafe; EXTERN Multab multab[20]; EXTERN int mnstring; -EXTERN int retok; EXTERN Node* nodrat; EXTERN Node* nodret; EXTERN Node* nodsafe; +EXTERN Node* nodretv; EXTERN long nrathole; EXTERN long nstring; EXTERN Prog* p; @@ -244,8 +246,11 @@ void regind(Node*, Node*); void gprep(Node*, Node*); void raddr(Node*, Prog*); void naddr(Node*, Adr*); +void gloadhi(Node*, Node*, int); +void gloadlo(Node*, Node*, int); void gmove(Node*, Node*); void gins(int a, Node*, Node*); +void gins3(int a, Node*, Node*, Node*); void gopcode(int, Node*, Node*, Node*); int samaddr(Node*, Node*); void gbranch(int); @@ -253,6 +258,10 @@ void patch(Prog*, long); int sconst(Node*); int sval(long); int uconst(Node*); +long hi64v(Node*); +long lo64v(Node*); +Node* hi64(Node*); +Node* lo64(Node*); void gpseudo(int, Sym*, Node*); /* @@ -260,8 +269,9 @@ void gpseudo(int, Sym*, Node*); */ int swcmp(void*, void*); void doswit(Node*); -void swit1(C1*, int, long, Node*, Node*); -void cas(void); +void swit1(C1*, int, long, Node*); +void swit2(C1*, int, long, Node*, Node*); +void casf(void); void bitload(Node*, Node*, Node*, Node*, Node*); void bitstore(Node*, Node*, Node*, Node*, Node*); long outstring(char*, long); diff --git a/utils/qc/list.c b/utils/qc/list.c index 3538c621..2f7eeb18 100644 --- a/utils/qc/list.c +++ b/utils/qc/list.c @@ -72,7 +72,7 @@ Aconv(Fmt *fp) a = va_arg(fp->args, int); s = "???"; - if(a >= AXXX && a <= AEND) + if(a >= AXXX && a <= ALAST) s = anames[a]; return fmtstrcpy(fp, s); } diff --git a/utils/qc/machcap.c b/utils/qc/machcap.c new file mode 100644 index 00000000..5fae5731 --- /dev/null +++ b/utils/qc/machcap.c @@ -0,0 +1,16 @@ +#include "gc.h" + +/* default, like old cc */ +int +machcap(Node *n) +{ + if(n == Z) + return 0; /* test */ + switch(n->op){ + case OCOMMA: + case OCOND: + case OLIST: + return 1; + } + return 0; +} diff --git a/utils/qc/mkfile b/utils/qc/mkfile index 21933876..19258dba 100644 --- a/utils/qc/mkfile +++ b/utils/qc/mkfile @@ -3,14 +3,17 @@ TARG=qc OFILES=\ cgen.$O\ - reg.$O\ - txt.$O\ - peep.$O\ - swt.$O\ - sgen.$O\ - list.$O\ enam.$O\ + list.$O\ + machcap.$O\ mul.$O\ + peep.$O\ + pgen.$O\ + pswt.$O\ + reg.$O\ + sgen.$O\ + swt.$O\ + txt.$O\ HFILES=\ gc.h\ @@ -27,3 +30,9 @@ $ROOT/$OBJDIR/lib/libcc.a: cd ../cc mk $MKFLAGS install mk $MKFLAGS clean + +%.$O: ../cc/%.c + $CC $CFLAGS ../cc/$stem.c + +#enam.c: q.out.h +# rc mkenam diff --git a/utils/qc/peep.c b/utils/qc/peep.c index 69d021be..cf1114f0 100644 --- a/utils/qc/peep.c +++ b/utils/qc/peep.c @@ -167,7 +167,16 @@ loop1: case AORNCC: case AXORCC: case ASUBCC: + case ASUBECC: + case ASUBMECC: + case ASUBZECC: case AADDCC: + case AADDCCC: + case AADDECC: + case AADDMECC: + case AADDZECC: + case ARLWMICC: + case ARLWNMCC: t = p1->as; break; /* don't deal with floating point instructions for now */ @@ -269,6 +278,7 @@ excise(Reg *r) p = r->prog; p->as = ANOP; p->from = zprog.from; + p->from3 = zprog.from3; p->to = zprog.to; p->reg = zprog.reg; /**/ } @@ -309,7 +319,6 @@ uniqs(Reg *r) * if the system forces R0 to be zero, * convert references to $0 to references to R0. */ -int regzer(Adr *a) { if(R0ISZERO) { @@ -324,7 +333,6 @@ regzer(Adr *a) return 0; } -int regtyp(Adr *a) { @@ -376,10 +384,22 @@ subprop(Reg *r0) return 0; case AADD: + case AADDC: + case AADDCC: + case AADDE: + case AADDECC: case ASUB: + case ASUBCC: + case ASUBC: + case ASUBCCC: + case ASUBE: + case ASUBECC: case ASLW: + case ASLWCC: case ASRW: + case ASRWCC: case ASRAW: + case ASRAWCC: case AOR: case AORCC: case AORN: @@ -394,13 +414,17 @@ subprop(Reg *r0) case ANORCC: case AXOR: case AXORCC: + case AMULHW: + case AMULHWU: case AMULLW: case ADIVW: case ADIVWU: case AREM: case AREMU: - case ANEG: - case ANEGCC: + case ARLWNM: + case ARLWNMCC: + case ARLWMI: + case ARLWMICC: case AFADD: case AFADDS: @@ -410,8 +434,6 @@ subprop(Reg *r0) case AFMULS: case AFDIV: case AFDIVS: - case AFNEG: - case AFNEGCC: if(p->to.type == v1->type) if(p->to.reg == v1->reg) { if(p->reg == NREG) @@ -420,6 +442,18 @@ subprop(Reg *r0) } break; + case AADDME: + case AADDMECC: + case AADDZE: + case AADDZECC: + case ASUBME: + case ASUBMECC: + case ASUBZE: + case ASUBZECC: + case ANEG: + case ANEGCC: + case AFNEG: + case AFNEGCC: case AFMOVS: case AFMOVD: case AMOVW: @@ -492,7 +526,6 @@ copyprop(Reg *r0) return copy1(v1, v2, r0->s1, 0); } -int copy1(Adr *v1, Adr *v2, Reg *r, int f) { int t; @@ -585,7 +618,7 @@ copyu(Prog *p, Adr *v, Adr *s) default: if(debug['P']) - print(" (?)"); + print(" (???)"); return 2; @@ -598,6 +631,14 @@ copyu(Prog *p, Adr *v, Adr *s) case ANEG: case ANEGCC: + case AADDME: + case AADDMECC: + case AADDZE: + case AADDZECC: + case ASUBME: + case ASUBMECC: + case ASUBZE: + case ASUBZECC: case AFCTIW: case AFCTIWZ: @@ -626,6 +667,8 @@ copyu(Prog *p, Adr *v, Adr *s) return 0; case AADD: /* read read write */ + case AADDC: + case AADDE: case ASUB: case ASLW: case ASRW: @@ -643,11 +686,17 @@ copyu(Prog *p, Adr *v, Adr *s) case ANOR: case ANORCC: case AXOR: + case AMULHW: + case AMULHWU: case AMULLW: case ADIVW: case ADIVWU: case AREM: case AREMU: + case ARLWMI: + case ARLWMICC: + case ARLWNM: + case ARLWNMCC: case AFADDS: case AFADD: @@ -763,9 +812,25 @@ a2type(Prog *p) switch(p->as) { case AADD: + case AADDC: case AADDCC: + case AADDCCC: + case AADDE: + case AADDECC: + case AADDME: + case AADDMECC: + case AADDZE: + case AADDZECC: case ASUB: + case ASUBC: case ASUBCC: + case ASUBCCC: + case ASUBE: + case ASUBECC: + case ASUBME: + case ASUBMECC: + case ASUBZE: + case ASUBZECC: case ASLW: case ASLWCC: case ASRW: @@ -784,6 +849,8 @@ a2type(Prog *p) case AXORCC: case ANEG: case ANEGCC: + case AMULHW: + case AMULHWU: case AMULLW: case AMULLWCC: case ADIVW: @@ -798,6 +865,10 @@ a2type(Prog *p) case ANANDCC: case ANOR: case ANORCC: + case ARLWMI: + case ARLWMICC: + case ARLWNM: + case ARLWNMCC: return D_REG; case AFADDS: diff --git a/utils/qc/q.out.h b/utils/qc/q.out.h index 795da7f7..1c5a141e 100644 --- a/utils/qc/q.out.h +++ b/utils/qc/q.out.h @@ -169,21 +169,11 @@ enum as AMOVW, AMOVWU, AMOVFL, - AMOVCRFXXX, AMOVCRFS, - AMOVCRXRXXX, - AMOVFCRXXX, - AMFFSXXX, - AMFFSCCXXX, - AMTCRFXXX, AMTFSB0, AMTFSB0CC, AMTFSB1, AMTFSB1CC, - AMTFSFXXX, - AMTFSFCCXXX, - AMTFSFIXXX, - AMTFSFIXXXCC, AMULHW, AMULHWCC, AMULHWU, @@ -223,9 +213,7 @@ enum as ASRAW, ASRAWCC, ASRWCC, - AILLXXX1, ASTSW, - ASTWBRXXX, ASTWCCC, ASUB, ASUBCC, @@ -368,6 +356,83 @@ enum as ARFCI, + /* optional on 32-bit */ + AFRES, + AFRESCC, + AFRSQRTE, + AFRSQRTECC, + AFSEL, + AFSELCC, + AFSQRT, + AFSQRTCC, + AFSQRTS, + AFSQRTSCC, + + /* parallel, cross, and secondary */ + AFPSEL, + AFPMUL, + AFXMUL, + AFXPMUL, + AFXSMUL, + AFPADD, + AFPSUB, + AFPRE, + AFPRSQRTE, + AFPMADD, + AFXMADD, + AFXCPMADD, + AFXCSMADD, + AFPNMADD, + AFXNMADD, + AFXCPNMADD, + AFXCSNMADD, + AFPMSUB, + AFXMSUB, + AFXCPMSUB, + AFXCSMSUB, + AFPNMSUB, + AFXNMSUB, + AFXCPNMSUB, + AFXCSNMSUB, + AFPMOVD, + AFPABS, + AFPNEG, + AFPRSP, + AFPNABS, + AFSMOVD, + AFSCMP, + AFSABS, + AFSNEG, + AFSNABS, + AFXMOVD, + AFPCTIW, + AFPCTIWZ, + AFSMOVP, + AFPMOVS, + AFXCPNPMA, + AFXCSNPMA, + AFXCPNSMA, + AFXCSNSMA, + AFXCXNPMA, + AFXCXNSMA, + AFXCXMA, + AFXCXNMS, + + /* parallel, cross, and secondary load and store */ + AFMOVSS, + AFMOVSSU, + AFMOVSD, + AFMOVSDU, + AFMOVXS, + AFMOVSXU, + AFMOVXD, + AFMOVXDU, + AFMOVPS, + AFMOVPSU, + AFMOVPD, + AFMOVPDU, + AFMOVPIW, + ALAST }; diff --git a/utils/qc/reg.c b/utils/qc/reg.c index c1a900b0..33152f27 100644 --- a/utils/qc/reg.c +++ b/utils/qc/reg.c @@ -840,7 +840,6 @@ allreg(ulong b, Rgn *r) } break; - case TVLONG: case TDOUBLE: case TFLOAT: i = BtoF(~b); diff --git a/utils/qc/sgen.c b/utils/qc/sgen.c index d557d375..37542ebb 100644 --- a/utils/qc/sgen.c +++ b/utils/qc/sgen.c @@ -1,381 +1,6 @@ #include "gc.h" void -codgen(Node *n, Node *nn) -{ - Prog *sp; - Node *n1, nod, nod1; - - cursafe = 0; - curarg = 0; - maxargsafe = 0; - - /* - * isolate name - */ - for(n1 = nn;; n1 = n1->left) { - if(n1 == Z) { - diag(nn, "cant find function name"); - return; - } - if(n1->op == ONAME) - break; - } - nearln = nn->lineno; - gpseudo(ATEXT, n1->sym, nodconst(stkoff)); - sp = p; - - /* - * isolate first argument - */ - if(REGARG) { - if(typesuv[thisfn->link->etype]) { - nod1 = *nodret->left; - nodreg(&nod, &nod1, REGARG); - gopcode(OAS, &nod, Z, &nod1); - } else - if(firstarg && typechlp[firstargtype->etype]) { - nod1 = *nodret->left; - nod1.sym = firstarg; - nod1.type = firstargtype; - nod1.xoffset = align(0, firstargtype, Aarg1); - nod1.etype = firstargtype->etype; - nodreg(&nod, &nod1, REGARG); - gopcode(OAS, &nod, Z, &nod1); - } - } - - retok = 0; - gen(n); - if(!retok) - if(thisfn->link->etype != TVOID) - warn(Z, "no return at end of function: %s", n1->sym->name); - noretval(3); - gbranch(ORETURN); - - if(!debug['N'] || debug['R'] || debug['P']) - regopt(sp); - - sp->to.offset += maxargsafe; -} - -void -supgen(Node *n) -{ - long spc; - Prog *sp; - - if(n == Z) - return; - suppress++; - spc = pc; - sp = lastp; - gen(n); - lastp = sp; - pc = spc; - sp->link = nil; - suppress--; -} - -void -gen(Node *n) -{ - Node *l, nod; - Prog *sp, *spc, *spb; - Case *cn; - long sbc, scc; - int o, f; - -loop: - if(n == Z) - return; - nearln = n->lineno; - o = n->op; - if(debug['G']) - if(o != OLIST) - print("%L %O\n", nearln, o); - retok = 0; - switch(o) { - - default: - complex(n); - cgen(n, Z); - break; - - case OLIST: - gen(n->left); - - rloop: - n = n->right; - goto loop; - - case ORETURN: - retok = 1; - complex(n); - if(n->type == T) - break; - l = n->left; - if(l == Z) { - noretval(3); - gbranch(ORETURN); - break; - } - if(typesuv[n->type->etype]) { - sugen(l, nodret, n->type->width); - noretval(3); - gbranch(ORETURN); - break; - } - regret(&nod, n); - cgen(l, &nod); - regfree(&nod); - if(typefd[n->type->etype]) - noretval(1); - else - noretval(2); - gbranch(ORETURN); - break; - - case OLABEL: - l = n->left; - if(l) { - l->xoffset = pc; - if(l->label) - patch(l->label, pc); - } - gbranch(OGOTO); /* prevent self reference in reg */ - patch(p, pc); - goto rloop; - - case OGOTO: - retok = 1; - n = n->left; - if(n == Z) - return; - if(n->complex == 0) { - diag(Z, "label undefined: %s", n->sym->name); - return; - } - if(suppress) - return; - gbranch(OGOTO); - if(n->xoffset) { - patch(p, n->xoffset); - return; - } - if(n->label) - patch(n->label, pc-1); - n->label = p; - return; - - case OCASE: - l = n->left; - if(cases == C) - diag(n, "case/default outside a switch"); - if(l == Z) { - cas(); - cases->val = 0; - cases->def = 1; - cases->label = pc; - goto rloop; - } - complex(l); - if(l->type == T) - goto rloop; - if(l->op == OCONST) - if(typechl[l->type->etype]) { - cas(); - cases->val = l->vconst; - cases->def = 0; - cases->label = pc; - goto rloop; - } - diag(n, "case expression must be integer constant"); - goto rloop; - - case OSWITCH: - l = n->left; - complex(l); - if(l->type == T) - break; - if(!typechl[l->type->etype]) { - diag(n, "switch expression must be integer"); - break; - } - - gbranch(OGOTO); /* entry */ - sp = p; - - cn = cases; - cases = C; - cas(); - - sbc = breakpc; - breakpc = pc; - gbranch(OGOTO); - spb = p; - - gen(n->right); - gbranch(OGOTO); - patch(p, breakpc); - - patch(sp, pc); - regalloc(&nod, l, Z); - nod.type = types[TLONG]; - cgen(l, &nod); - doswit(&nod); - regfree(&nod); - patch(spb, pc); - - cases = cn; - breakpc = sbc; - break; - - case OWHILE: - case ODWHILE: - l = n->left; - gbranch(OGOTO); /* entry */ - sp = p; - - scc = continpc; - continpc = pc; - gbranch(OGOTO); - spc = p; - - sbc = breakpc; - breakpc = pc; - gbranch(OGOTO); - spb = p; - - patch(spc, pc); - if(n->op == OWHILE) - patch(sp, pc); - bcomplex(l, Z); /* test */ - patch(p, breakpc); - - if(n->op == ODWHILE) - patch(sp, pc); - gen(n->right); /* body */ - gbranch(OGOTO); - patch(p, continpc); - - patch(spb, pc); - continpc = scc; - breakpc = sbc; - break; - - case OFOR: - l = n->left; - gen(l->right->left); /* init */ - gbranch(OGOTO); /* entry */ - sp = p; - - scc = continpc; - continpc = pc; - gbranch(OGOTO); - spc = p; - - sbc = breakpc; - breakpc = pc; - gbranch(OGOTO); - spb = p; - - patch(spc, pc); - gen(l->right->right); /* inc */ - patch(sp, pc); - if(l->left != Z) { /* test */ - bcomplex(l->left, Z); - patch(p, breakpc); - } - gen(n->right); /* body */ - gbranch(OGOTO); - patch(p, continpc); - - patch(spb, pc); - continpc = scc; - breakpc = sbc; - break; - - case OCONTINUE: - if(continpc < 0) { - diag(n, "continue not in a loop"); - break; - } - gbranch(OGOTO); - patch(p, continpc); - break; - - case OBREAK: - if(breakpc < 0) { - diag(n, "break not in a loop"); - break; - } - gbranch(OGOTO); - patch(p, breakpc); - break; - - case OIF: - l = n->left; - if(bcomplex(l, n->right)) { - if(typefd[l->type->etype]) - f = !l->fconst; - else - f = !l->vconst; - if(debug['c']) - print("%L const if %s\n", nearln, f ? "false" : "true"); - if(f) { - supgen(n->right->left); - gen(n->right->right); - } - else { - gen(n->right->left); - supgen(n->right->right); - } - } - else { - sp = p; - if(n->right->left != Z) - gen(n->right->left); - if(n->right->right != Z) { - gbranch(OGOTO); - patch(sp, pc); - sp = p; - gen(n->right->right); - } - patch(sp, pc); - } - break; - - case OSET: - case OUSED: - usedset(n->left, o); - break; - } -} - -void -usedset(Node *n, int o) -{ - if(n->op == OLIST) { - usedset(n->left, o); - usedset(n->right, o); - return; - } - complex(n); - switch(n->op) { - case OADDR: /* volatile */ - gins(ANOP, n, Z); - break; - case ONAME: - if(o == OSET) - gins(ANOP, Z, n); - else - gins(ANOP, n, Z); - break; - } -} - -void noretval(int n) { @@ -410,7 +35,7 @@ void xcom(Node *n) { Node *l, *r; - int v; + int v, nr; if(n == Z) return; @@ -568,14 +193,23 @@ xcom(Node *n) if(l != Z) n->complex = l->complex; if(r != Z) { + nr = 1; + if(r->type != T && typev[r->type->etype] || n->type != T && typev[n->type->etype]) { + nr = 2; + if(n->op == OMUL || n->op == OLMUL) + nr += 3; + } if(r->complex == n->complex) - n->complex = r->complex+1; + n->complex = r->complex+nr; else if(r->complex > n->complex) n->complex = r->complex; } - if(n->complex == 0) + if(n->complex == 0){ n->complex++; + if(n->type != T && typev[n->type->etype]) + n->complex++; + } if(com64(n)) return; @@ -621,20 +255,3 @@ xcom(Node *n) } } -int -bcomplex(Node *n, Node *c) -{ - - complex(n); - if(n->type != T) - if(tcompat(n, T, n->type, tnot)) - n->type = T; - if(n->type != T) { - if(c != Z && n->op == OCONST && deadheads(c)) - return 1; - bool64(n); - boolgen(n, 1, Z); - } else - gbranch(OGOTO); - return 0; -} diff --git a/utils/qc/swt.c b/utils/qc/swt.c index 9bf0e58e..0170bad1 100644 --- a/utils/qc/swt.c +++ b/utils/qc/swt.c @@ -1,59 +1,20 @@ #include "gc.h" -int -swcmp(void *a1, void *a2) -{ - C1 *p1, *p2; - - p1 = a1; - p2 = a2; - if(p1->val < p2->val) - return -1; - return p1->val > p2->val; -} +int hasdoubled; +static int doubleflag; void -doswit(Node *n) +swit1(C1 *q, int nc, long def, Node *n) { - Case *c; - C1 *q, *iq; - long def, nc, i; Node tn; - - def = 0; - nc = 0; - for(c = cases; c->link != C; c = c->link) { - if(c->def) { - if(def) - diag(n, "more than one default in switch"); - def = c->label; - continue; - } - nc++; - } - - iq = alloc(nc*sizeof(C1)); - q = iq; - for(c = cases; c->link != C; c = c->link) { - if(c->def) - continue; - q->label = c->label; - q->val = c->val; - q++; - } - qsort(iq, nc, sizeof(C1), swcmp); - if(def == 0) - def = breakpc; - for(i=0; i<nc-1; i++) - if(iq[i].val == iq[i+1].val) - diag(n, "duplicate cases in switch %ld", iq[i].val); + regalloc(&tn, ®node, Z); - swit1(iq, nc, def, n, &tn); + swit2(q, nc, def, n, &tn); regfree(&tn); } void -swit1(C1 *q, int nc, long def, Node *n, Node *tn) +swit2(C1 *q, int nc, long def, Node *n, Node *tn) { C1 *r; int i; @@ -87,20 +48,10 @@ swit1(C1 *q, int nc, long def, Node *n, Node *tn) gbranch(OGOTO); p->as = ABEQ; patch(p, r->label); - swit1(q, i, def, n, tn); + swit2(q, i, def, n, tn); patch(sp, pc); - swit1(r+1, nc-i-1, def, n, tn); -} - -void -cas(void) -{ - Case *c; - - c = alloc(sizeof(*c)); - c->link = cases; - cases = c; + swit2(r+1, nc-i-1, def, n, tn); } void @@ -200,33 +151,6 @@ outstring(char *s, long n) return r; } -long -outlstring(ushort *s, long n) -{ - char buf[2]; - int c; - long r; - - if(suppress) - return nstring; - while(nstring & 1) - outstring("", 1); - r = nstring; - while(n > 0) { - c = *s++; - if(align(0, types[TCHAR], Aarg1)) { - buf[0] = c>>8; - buf[1] = c; - } else { - buf[0] = c; - buf[1] = c>>8; - } - outstring(buf, 2); - n -= sizeof(ushort); - } - return r; -} - int mulcon(Node *n, Node *nn) { @@ -317,16 +241,6 @@ loop: } void -nullwarn(Node *l, Node *r) -{ - warn(Z, "result of operation not used"); - if(l != Z) - cgen(l, Z); - if(r != Z) - cgen(r, Z); -} - -void sextern(Sym *s, Node *a, long o, long w) { long e, lw; @@ -454,13 +368,14 @@ zwrite(Biobuf *b, Prog *p, int sf, int st) long l; bf[0] = p->as; - bf[1] = p->reg; + bf[1] = p->as>>8; + bf[2] = p->reg; l = p->lineno; - bf[2] = l; - bf[3] = l>>8; - bf[4] = l>>16; - bf[5] = l>>24; - bp = zaddr(bf+6, &p->from, sf); + bf[3] = l; + bf[4] = l>>8; + bf[5] = l>>16; + bf[6] = l>>24; + bp = zaddr(bf+7, &p->from, sf); bp = zaddr(bp, &p->to, st); Bwrite(b, bf, bp-bf); } @@ -510,6 +425,7 @@ outhist(Biobuf *b) } if(n) { Bputc(b, ANAME); + Bputc(b, ANAME>>8); Bputc(b, D_FILE); Bputc(b, 1); Bputc(b, '<'); @@ -535,27 +451,29 @@ outhist(Biobuf *b) void zname(Biobuf *b, Sym *s, int t) { - char *n, bf[7]; + char *n, bf[8]; ulong sig; n = s->name; if(debug['T'] && t == D_EXTERN && s->sig != SIGDONE && s->type != types[TENUM] && s != symrathole){ sig = sign(s); bf[0] = ASIGNAME; - bf[1] = sig; - bf[2] = sig>>8; - bf[3] = sig>>16; - bf[4] = sig>>24; - bf[5] = t; - bf[6] = s->sym; - Bwrite(b, bf, 7); + bf[1] = ASIGNAME>>8; + bf[2] = sig; + bf[3] = sig>>8; + bf[4] = sig>>16; + bf[5] = sig>>24; + bf[6] = t; + bf[7] = s->sym; + Bwrite(b, bf, 8); s->sig = SIGDONE; } else{ bf[0] = ANAME; - bf[1] = t; /* type */ - bf[2] = s->sym; /* sym */ - Bwrite(b, bf, 3); + bf[1] = ANAME>>8; + bf[2] = t; /* type */ + bf[3] = s->sym; /* sym */ + Bwrite(b, bf, 4); } Bwrite(b, n, strlen(n)+1); } @@ -616,33 +534,32 @@ zaddr(char *bp, Adr *a, int s) return bp; } -void -ieeedtod(Ieee *ieee, double native) +static int +doubled(Type *t) { - double fr, ho, f; - int exp; + Type *v; - if(native < 0) { - ieeedtod(ieee, -native); - ieee->h |= 0x80000000L; - return; - } - if(native == 0) { - ieee->l = 0; - ieee->h = 0; - return; + if(debug['4']) + return 0; + if(t->nbits != 0) + return 0; + switch(t->etype){ + case TDOUBLE: + return 1; + + case TARRAY: + for(v=t; v->etype==TARRAY; v=v->link) + ; + return v->etype == TDOUBLE; + + case TSTRUCT: + case TUNION: + for(v = t->link; v != T; v = v->down) + if(doubled(v)) + return 1; + break; } - fr = frexp(native, &exp); - f = 2097152L; /* shouldnt use fp constants here */ - fr = modf(fr*f, &ho); - ieee->h = ho; - ieee->h &= 0xfffffL; - ieee->h |= (exp+1022L) << 20; - f = 65536L; - fr = modf(fr*f, &ho); - ieee->l = ho; - ieee->l <<= 16; - ieee->l |= (long)(fr*f); + return 0; } long @@ -650,27 +567,33 @@ align(long i, Type *t, int op) { long o; Type *v; - int w; + int w, pc; o = i; w = 1; + pc = 0; switch(op) { default: diag(Z, "unknown align opcode %d", op); break; case Asu2: /* padding at end of a struct */ - w = SZ_LONG; + w = doubled(t)? SZ_DOUBLE: SZ_LONG; if(packflg) w = packflg; break; - case Ael1: /* initial allign of struct element */ + case Ael1: /* initial align of struct element (also automatic) */ for(v=t; v->etype==TARRAY; v=v->link) ; w = ewidth[v->etype]; - if(w <= 0 || w >= SZ_LONG) - w = SZ_LONG; + if(w <= 0 || w >= SZ_LONG){ + if(doubled(v)){ + w = SZ_DOUBLE; + doubleflag = 1; + }else + w = SZ_LONG; + } if(packflg) w = packflg; break; @@ -686,10 +609,15 @@ align(long i, Type *t, int op) } break; - case Aarg1: /* initial allign of parameter */ + case Aarg1: /* initial align of parameter */ w = ewidth[t->etype]; if(w <= 0 || w >= SZ_LONG) { - w = SZ_LONG; + if(doubled(t)){ + w = SZ_DOUBLE; + pc = SZ_LONG; /* alignment must account for pc */ + hasdoubled = 1; + }else + w = SZ_LONG; break; } o += SZ_LONG - w; /* big endian adjustment */ @@ -699,14 +627,20 @@ align(long i, Type *t, int op) case Aarg2: /* width of a parameter */ o += t->width; w = SZ_LONG; + if(doubled(t)){ + pc = SZ_LONG; + hasdoubled = 1; + } break; - case Aaut3: /* total allign of automatic */ + case Aaut3: /* total align of automatic */ + doubleflag = 0; o = align(o, t, Ael1); o = align(o, t, Ael2); + hasdoubled |= doubleflag; break; } - o = round(o, w); + o = round(o+pc, w)-pc; if(debug['A']) print("align %s %ld %T = %ld\n", bnames[op], i, t, o); return o; @@ -715,8 +649,13 @@ align(long i, Type *t, int op) long maxround(long max, long v) { - v += SZ_LONG-1; + int w; + + w = SZ_LONG; + if((debug['8'] || hasdoubled) && !debug['4']) + w = SZ_DOUBLE; + v += w-1; if(v > max) - max = round(v, SZ_LONG); + max = round(v, w); return max; } diff --git a/utils/qc/txt.c b/utils/qc/txt.c index c14386ac..d8102433 100644 --- a/utils/qc/txt.c +++ b/utils/qc/txt.c @@ -2,6 +2,9 @@ static int resvreg[nelem(reg)]; +static void gopcode64(int, Node*, Node*, Node*); +static void gori64(int, Node*, Node*, Node*); +static void gandi64(int, Node*, Node*, Node*); void ginit(void) @@ -30,6 +33,7 @@ ginit(void) zprog.from.type = D_NONE; zprog.from.name = D_NONE; zprog.from.reg = NREG; + zprog.from3 = zprog.from; zprog.to = zprog.from; regnode.op = OREGISTER; @@ -71,14 +75,6 @@ ginit(void) complex(nodrat); nodrat->type = t; - nodret = new(ONAME, Z, Z); - nodret->sym = slookup(".ret"); - nodret->type = types[TIND]; - nodret->etype = TIND; - nodret->class = CPARAM; - nodret = new(OIND, nodret, Z); - complex(nodret); - com64init(); memset(reg, 0, sizeof(reg)); @@ -188,10 +184,10 @@ garg1(Node *n, Node *tn1, Node *tn2, int f, Node **fnxp) if(typesuv[n->type->etype]) { regaalloc(tn2, n); if(n->complex >= FNX) { - sugen(*fnxp, tn2, n->type->width); + cgen(*fnxp, tn2); (*fnxp)++; } else - sugen(n, tn2, n->type->width); + cgen(n, tn2); return; } if(REGARG && curarg == 0 && typechlp[n->type->etype]) { @@ -314,6 +310,27 @@ regalloc(Node *n, Node *tn, Node *o) } diag(tn, "out of float registers"); goto err; + + case TVLONG: + case TUVLONG: + n->op = OREGPAIR; + n->complex = 0; /* already in registers */ + n->addable = 11; + n->type = tn->type; + n->lineno = nearln; + n->left = alloc(sizeof(Node)); + n->right = alloc(sizeof(Node)); + if(o != Z && o->op == OREGPAIR) { + regalloc(n->left, ®node, o->left); + regalloc(n->right, ®node, o->right); + } else { + regalloc(n->left, ®node, Z); + regalloc(n->right, ®node, Z); + } + n->right->type = types[TULONG]; + if(tn->type->etype == TUVLONG) + n->left->type = types[TULONG]; /* TO DO: is this a bad idea? */ + return; } diag(tn, "unknown type in regalloc: %T", tn->type); err: @@ -342,6 +359,11 @@ regfree(Node *n) { int i; + if(n->op == OREGPAIR) { + regfree(n->left); + regfree(n->right); + return; + } i = 0; if(n->op != OREGISTER && n->op != OINDREG) goto err; @@ -353,14 +375,19 @@ regfree(Node *n) reg[i]--; return; err: - diag(n, "error in regfree: %d", i); + diag(n, "error in regfree: %d [%d]", i, reg[i]); + prtree(n, "regfree"); } void regsalloc(Node *n, Node *nn) { - cursafe = align(cursafe, nn->type, Aaut3); + cursafe = align(cursafe+stkoff, nn->type, Aaut3)-stkoff; maxargsafe = maxround(maxargsafe, cursafe+curarg); +// if(nn->type->etype == TDOUBLE || nn->type->etype == TVLONG){ +// extern int hasdoubled; +// fprint(2, "stkoff=%ld cursafe=%ld curarg=%ld %d\n", stkoff, cursafe, curarg, hasdoubled); +// } *n = *nodsafe; n->xoffset = -(stkoff + cursafe); n->type = nn->type; @@ -450,6 +477,7 @@ naddr(Node *n, Adr *a) case OIND: naddr(n->left, a); + a->offset += n->xoffset; /* little hack for reglcgenv */ if(a->type == D_REG) { a->type = D_OREG; break; @@ -526,6 +554,59 @@ naddr(Node *n, Adr *a) } void +gloadhi(Node *f, Node *t, int c) +{ + Type *ot; + + if(f->op == OCONST){ + f = nodconst((long)(f->vconst>>32)); + if(c==1 && sconst(f) || c==2 && uconst(f)){ + if(t->op == OREGISTER) + regfree(t); + *t = *f; + return; + } + } + if(f->op == OREGPAIR) { + gmove(f->left, t); + return; + } + ot = f->type; + f->type = types[TLONG]; + gmove(f, t); + f->type = ot; +} + +void +gloadlo(Node *f, Node *t, int c) +{ + Type *ot; + + if(f->op == OCONST){ + f = nodconst((long)f->vconst); + if(c && uconst(f)){ + if(t->op == OREGISTER) + regfree(t); + *t = *f; + return; + } + } + if(f->op == OREGPAIR) { + gmove(f->right, t); + return; + } + ot = f->type; + f->type = types[TLONG]; + f->xoffset += SZ_LONG; + if(0){ + prtree(f, "gloadlo f"); prtree(t, "gloadlo t"); + } + gmove(f, t); + f->xoffset -= SZ_LONG; + f->type = ot; +} + +void fop(int as, int f1, int f2, Node *t) { Node nod1, nod2, nod3; @@ -602,6 +683,17 @@ gmove(Node *f, Node *t) return; } } + if((ft == TVLONG || ft == TUVLONG) && f->op == OCONST && t->op == OREGPAIR) { + if(align(0, types[TCHAR], Aarg1)) /* isbigendian */ + gmove(nod32const(f->vconst>>32), t->left); + else + gmove(nod32const(f->vconst), t->left); + if(align(0, types[TCHAR], Aarg1)) /* isbigendian */ + gmove(nod32const(f->vconst), t->right); + else + gmove(nod32const(f->vconst>>32), t->right); + return; + } /* * a load -- * put it into a register then @@ -631,8 +723,25 @@ gmove(Node *f, Node *t) a = AMOVHZ; break; } - regalloc(&nod, f, t); - gins(a, f, &nod); + if(typev[ft]) { + if(typev[tt]) { + regalloc(&nod, f, t); + /* low order first, because its value will be used first */ + f->xoffset += SZ_LONG; + gins(AMOVW, f, nod.right); + f->xoffset -= SZ_LONG; + gins(AMOVW, f, nod.left); + } else { + /* assumed not float or double */ + regalloc(&nod, ®node, t); + f->xoffset += SZ_LONG; + gins(AMOVW, f, &nod); + f->xoffset -= SZ_LONG; + } + } else { + regalloc(&nod, f, t); + gins(a, f, &nod); + } gmove(&nod, t); regfree(&nod); return; @@ -669,6 +778,11 @@ gmove(Node *f, Node *t) } if(R0ISZERO && !typefd[ft] && vconst(f) == 0) { gins(a, f, t); + if(typev[tt]) { + t->xoffset += SZ_LONG; + gins(a, f, t); + t->xoffset -= SZ_LONG; + } return; } if(ft == tt) @@ -676,7 +790,13 @@ gmove(Node *f, Node *t) else regalloc(&nod, t, Z); gmove(f, &nod); - gins(a, &nod, t); + if(typev[tt]) { + t->xoffset += SZ_LONG; + gins(a, nod.right, t); + t->xoffset -= SZ_LONG; + gins(a, nod.left, t); + } else + gins(a, &nod, t); regfree(&nod); return; } @@ -710,7 +830,7 @@ gmove(Node *f, Node *t) case TUCHAR: /* BUG: not right for unsigned long */ regalloc(&nod, f, Z); /* should be type float */ - regsalloc(&fxrat, f); + regsalloc(&fxrat, &fconstnode); gins(AFCTIWZ, f, &nod); gins(AFMOVD, &nod, &fxrat); regfree(&nod); @@ -817,7 +937,7 @@ gmove(Node *f, Node *t) */ regalloc(&fxc0, f, Z); regalloc(&fxc2, f, Z); - regsalloc(&fxrat, t); /* should be type float */ + regsalloc(&fxrat, &fconstnode); /* should be type float */ gins(AMOVW, nodconst(0x43300000L), &fxc0); gins(AMOVW, f, &fxc2); gins(AMOVW, &fxc0, &fxrat); @@ -876,13 +996,28 @@ gmove(Node *f, Node *t) break; } break; + case TVLONG: + case TUVLONG: + switch(tt) { + case TVLONG: + case TUVLONG: + a = AMOVW; + break; + } + break; } if(a == AGOK) diag(Z, "bad opcode in gmove %T -> %T", f->type, t->type); if(a == AMOVW || a == AFMOVS || a == AFMOVD) if(samaddr(f, t)) return; - gins(a, f, t); + if(typev[ft]) { + if(f->op != OREGPAIR || t->op != OREGPAIR) + diag(Z, "bad vlong in gmove (%O->%O)", f->op, t->op); + gins(a, f->left, t->left); + gins(a, f->right, t->right); + } else + gins(a, f, t); } void @@ -900,21 +1035,75 @@ gins(int a, Node *f, Node *t) } void -gopcode(int o, Node *f1, Node *f2, Node *t) +gins3(int a, Node *f1, Node *f2, Node *t) { - int a, et; Adr ta; - int uns; - uns = 0; + nextpc(); + p->as = a; + if(f1 != Z) + naddr(f1, &p->from); + if(f2 != Z && (f2->op != OREGISTER || !samaddr(f2, t))) { + ta = zprog.from; /* TO DO */ + naddr(f2, &ta); + p->reg = ta.reg; + if(ta.type == D_CONST && ta.offset == 0) { + if(R0ISZERO) + p->reg = REGZERO; + else + diag(Z, "REGZERO in gins3 %A", a); + }else if(ta.type == D_CONST) + p->from3 = ta; + } + if(t != Z) + naddr(t, &p->to); + if(debug['g']) + print("%P\n", p); +} + +void +gins4(int a, Node *f1, Node *f2, Node *f3, Node *t) +{ + Adr ta; + + nextpc(); + p->as = a; + naddr(f1, &p->from); + if(f2->op != OREGISTER && (f2->op != OCONST || vconst(f2) != 0)) + diag(f2, "invalid gins4"); + naddr(f2, &ta); + p->reg = ta.reg; + if(ta.type == D_CONST && ta.offset == 0) + p->reg = REGZERO; + naddr(f3, &p->from3); + naddr(t, &p->to); + if(debug['g']) + print("%P\n", p); +} + +void +gopcode(int o, Node *f1, Node *f2, Node *t) +{ + int a, et, uns; + + if(o == OAS) { + gmove(f1, t); + return; + } et = TLONG; - if(f1 != Z && f1->type != T) - et = f1->type->etype; + if(f1 != Z && f1->type != T) { + if(f1->op == OCONST && t != Z && t->type != T) + et = t->type->etype; + else + et = f1->type->etype; + } + if((typev[et] || t->type != T && typev[t->type->etype]) && o != OFUNC) { + gopcode64(o, f1, f2, t); + return; + } + uns = 0; a = AGOK; switch(o) { - case OAS: - gmove(f1, t); - return; case OASADD: case OADD: @@ -965,7 +1154,7 @@ gopcode(int o, Node *f1, Node *f2, Node *t) case OASASHL: case OASHL: - a = ASLW; /* BUG? */ + a = ASLW; break; case OFUNC: @@ -1027,10 +1216,14 @@ gopcode(int o, Node *f1, Node *f2, Node *t) case OEQ: a = ABEQ; + if(t->op == OCONST && t->vconst >= (1<<15)) + goto cmpu; goto cmp; case ONE: a = ABNE; + if(t->op == OCONST && t->vconst >= (1<<15)) + goto cmpu; goto cmp; case OLT: @@ -1090,24 +1283,258 @@ gopcode(int o, Node *f1, Node *f2, Node *t) } if(a == AGOK) diag(Z, "bad in gopcode %O", o); - nextpc(); - p->as = a; - if(f1 != Z) - naddr(f1, &p->from); - if(f2 != Z) { - naddr(f2, &ta); - p->reg = ta.reg; - if(ta.type == D_CONST && ta.offset == 0) { - if(R0ISZERO) - p->reg = REGZERO; + gins3(a, f1, f2, t); +} + +static void +gopcode64(int o, Node *f1, Node *f2, Node *t) +{ + int a1, a2; + Node nod, nod1, nod2, sh; + ulong m; + Prog *p1; + + if(t->op != OREGPAIR || f2 != Z && f2->op != OREGPAIR) { + diag(Z, "bad f2/dest in gopcode64 %O", o); + return; + } + if(f1->op != OCONST && + (typev[f1->type->etype] && f1->op != OREGPAIR || !typev[f1->type->etype] && f1->op != OREGISTER)) { + diag(Z, "bad f1[%O] in gopcode64 %O", f1->op, o); + return; + } + /* a1 for low-order, a2 for high-order */ + a1 = AGOK; + a2 = AGOK; + switch(o) { + case OASADD: + case OADD: + if(f1->op == OCONST && sconst(f1)) { + if(f2 == Z) + f2 = t; + gins3(AADDC, f1, f2->right, t->right); + if((f1->vconst>>32) == 0) + gins(AADDZE, f2->left, t->left); + else if((f1->vconst>>32) == -1) + gins(AADDME, f2->left, t->left); else - diag(Z, "REGZERO in gopcode %O", o); + diag(t, "odd vlong ADD: %lld", f1->vconst); + return; + } + a1 = AADDC; + a2 = AADDE; + break; + + case OASSUB: + case OSUB: + a1 = ASUBC; + a2 = ASUBE; + break; + + case OASOR: + case OOR: + if(f1->op == OCONST) { + gori64(AOR, f1, f2, t); + return; + } + a1 = a2 = AOR; + break; + + case OASAND: + case OAND: + if(f1->op == OCONST) { + gandi64(AANDCC, f1, f2, t); + return; + } + a1 = a2 = AAND; + break; + + case OASXOR: + case OXOR: + if(f1->op == OCONST) { + gori64(AXOR, f1, f2, t); + return; + } + a1 = a2 = AXOR; + break; + + case OASLSHR: + case OLSHR: + if(f2 == Z) + f2 = t; + if(f1->op == OCONST) { + if(f1->vconst >= 32) { + if(f1->vconst == 32) + gmove(f2->left, t->right); + else if(f1->vconst < 64) + gins3(ASRW, nodconst(f1->vconst-32), f2->left, t->right); + else + gmove(nodconst(0), t->right); + gmove(nodconst(0), t->left); + return; + } + if(f1->vconst <= 0) { + if(f2 != t) + gmove(f2, t); + return; + } + sh = *nodconst(32 - f1->vconst); + m = 0xFFFFFFFFUL >> f1->vconst; + gins4(ARLWNM, &sh, f2->right, nodconst(m), t->right); + gins4(ARLWMI, &sh, f2->left, nodconst(~m), t->right); + gins4(ARLWNM, &sh, f2->left, nodconst(m), t->left); + return; + } + regalloc(&nod, ®node, Z); + gins3(ASUBC, f1, nodconst(32), &nod); + gins3(ASRW, f1, f2->right, t->right); + regalloc(&nod1, ®node, Z); + gins3(ASLW, &nod, f2->left, &nod1); + gins(AOR, &nod1, t->right); + gins3(AADD, nodconst(-32), f1, &nod); + gins3(ASRW, &nod, f2->left, &nod1); + gins(AOR, &nod1, t->right); + gins3(ASRW, f1, f2->left, t->left); + regfree(&nod); + regfree(&nod1); + return; + + case OASASHR: + case OASHR: + if(f2 == Z) + f2 = t; + if(f1->op == OCONST) { + if(f1->vconst >= 32) { + if(f1->vconst == 32) + gmove(f2->left, t->right); + else if(f1->vconst < 64) + gins3(ASRAW, nodconst(f1->vconst-32), f2->left, t->right); + gins3(ASRAW, nodconst(31), f2->left, t->left); + if(f1->vconst >= 64) { + gmove(t->left, t->right); + return; + } + return; + } + if(f1->vconst <= 0) { + if(f2 != t) + gmove(f2, t); + return; + } + sh = *nodconst(32 - f1->vconst); + m = 0xFFFFFFFFUL >> f1->vconst; + gins4(ARLWNM, &sh, f2->right, nodconst(m), t->right); + gins4(ARLWMI, &sh, f2->left, nodconst(~m), t->right); + gins3(ASRAW, &sh, f2->left, t->left); + return; + } + regalloc(&nod, ®node, Z); + gins3(ASUBC, f1, nodconst(32), &nod); + gins3(ASRW, f1, f2->right, t->right); + regalloc(&nod1, ®node, Z); + gins3(ASLW, &nod, f2->left, &nod1); + gins(AOR, &nod1, t->right); + gins3(AADDCCC, nodconst(-32), f1, &nod); + gins3(ASRAW, &nod, f2->left, &nod1); + gins(ABLE, Z, Z); + p1 = p; + gins(AMOVW, &nod1, t->right); + patch(p1, pc); + gins3(ASRAW, f1, f2->left, t->left); + regfree(&nod); + regfree(&nod1); + return; + + case OASASHL: + case OASHL: + if(f2 == Z) + f2 = t; + if(f1->op == OCONST) { + if(f1->vconst >= 32) { + if(f1->vconst == 32) + gmove(f2->right, t->left); + else if(f1->vconst >= 64) + gmove(nodconst(0), t->left); + else + gins3(ASLW, nodconst(f1->vconst-32), f2->right, t->left); + gmove(nodconst(0), t->right); + return; + } + if(f1->vconst <= 0) { + if(f2 != t) + gmove(f2, t); + return; + } + m = 0xFFFFFFFFUL << f1->vconst; + gins4(ARLWNM, f1, f2->left, nodconst(m), t->left); + gins4(ARLWMI, f1, f2->right, nodconst(~m), t->left); + gins4(ARLWNM, f1, f2->right, nodconst(m), t->right); + return; + } + regalloc(&nod, ®node, Z); + gins3(ASUBC, f1, nodconst(32), &nod); + gins3(ASLW, f1, f2->left, t->left); + regalloc(&nod1, ®node, Z); + gins3(ASRW, &nod, f2->right, &nod1); + gins(AOR, &nod1, t->left); + gins3(AADD, nodconst(-32), f1, &nod); + gins3(ASLW, &nod, f2->right, &nod1); + gins(AOR, &nod1, t->left); + gins3(ASLW, f1, f2->right, t->right); + regfree(&nod); + regfree(&nod1); + return; + + case OASLMUL: + case OLMUL: + case OASMUL: + case OMUL: + if(f2 == Z) + f2 = t; + regalloc(&nod, ®node, Z); + gins3(AMULLW, f1->right, f2->right, &nod); /* lo(f2.low*f1.low) */ + a1 = AMULHW; + if(o == OLMUL || o == OASLMUL) + a1 = AMULHWU; + regalloc(&nod1, ®node, Z); + gins3(a1, f1->right, f2->right, &nod1); /* hi(f2.low*f1.low) */ + regalloc(&nod2, ®node, Z); + gins3(AMULLW, f2->right, f1->left, &nod2); /* lo(f2.low*f1.high) */ + gins(AADD, &nod2, &nod1); + gins3(AMULLW, f1->right, f2->left, &nod2); /* hi(f2.high*f1.low) */ + gins(AADD, &nod2, &nod1); + regfree(&nod2); + gmove(&nod, t->right); + gmove(&nod1, t->left); + regfree(&nod); + regfree(&nod1); + return; + + case OCOM: + a1 = a2 = ANOR; + break; + + case ONEG: + gins3(ASUBC, t->right, nodconst(0), t->right); + gins(ASUBZE, t->left, t->left); + return; + } + if(a1 == AGOK || a2 == AGOK) + diag(Z, "bad in gopcode64 %O", o); + if(f1->op == OCONST) { + if(f2 != Z & f2 != t) + diag(Z, "bad const in gopcode64 %O", o); + gins(a1, nod32const(f1->vconst), t->right); + gins(a2, nod32const(f1->vconst>>32), t->left); + } else { + if(f2 != Z && f2 != t) { + gins3(a1, f1->right, f2->right, t->right); + gins3(a2, f1->left, f2->left, t->left); + } else { + gins(a1, f1->right, t->right); + gins(a2, f1->left, t->left); } } - if(t != Z) - naddr(t, &p->to); - if(debug['g']) - print("%P\n", p); } samaddr(Node *f, Node *t) @@ -1121,10 +1548,51 @@ samaddr(Node *f, Node *t) if(f->reg != t->reg) break; return 1; + + case OREGPAIR: + return samaddr(f->left, t->left) && samaddr(f->right, t->right); } return 0; } +static void +gori64(int a, Node *f1, Node *f2, Node *t) +{ + ulong lo, hi; + + if(f2 == Z) + f2 = t; + lo = f1->vconst & MASK(32); + hi = (f1->vconst >> 32) & MASK(32); + if(lo & 0xFFFF) + gins3(a, nodconst(lo & 0xFFFF), f2->right, t->right); + if((lo >> 16) != 0) + gins3(a, nodconst(lo & 0xFFFF0000UL), f2->right, t->right); + if(hi & 0xFFFF) + gins3(a, nodconst(hi & 0xFFFF), f2->left, t->left); + if((hi >> 16) != 0) + gins3(a, nodconst(hi & 0xFFFF0000UL), f2->left, t->left); +} + +static void +gandi64(int a, Node *f1, Node *f2, Node *t) +{ + ulong lo, hi; + + if(f2 == Z) + f2 = t; + lo = f1->vconst & MASK(32); + hi = (f1->vconst >> 32) & MASK(32); + if(lo == 0) + gins(AMOVW, nodconst(0), t->right); + else + gins3(a, nodconst(lo), f2->right, t->right); + if(hi == 0) + gins(AMOVW, nodconst(0), t->left); + else + gins3(a, nodconst(hi), f2->left, t->left); +} + void gbranch(int o) { diff --git a/utils/ql/asm.c b/utils/ql/asm.c index 0c546ee3..25d4c772 100644 --- a/utils/ql/asm.c +++ b/utils/ql/asm.c @@ -299,11 +299,21 @@ asmb(void) lput(1L); /* version = CURRENT */ lput(entryvalue() & ~KMASK); /* entry vaddr */ lput(52L); /* offset to first phdr */ - lput(0L); /* offset to first shdr */ - lput(0L); /* flags = PPC */ - lput((52L<<16)|32L); /* Ehdr & Phdr sizes*/ - lput((3L<<16)|0L); /* # Phdrs & Shdr size */ - lput((0L<<16)|0L); /* # Shdrs & shdr string size */ + + if(debug['S']){ + lput(HEADR+textsize+datsize+symsize); /* offset to first shdr */ + lput(0L); /* flags = PPC */ + lput((52L<<16)|32L); /* Ehdr & Phdr sizes*/ + lput((3L<<16)|40L); /* # Phdrs & Shdr size */ + lput((3L<<16)|2L); /* # Shdrs & shdr string size */ + } + else{ + lput(0L); + lput(0L); /* flags = PPC */ + lput((52L<<16)|32L); /* Ehdr & Phdr sizes*/ + lput((3L<<16)|0L); /* # Phdrs & Shdr size */ + lput((3L<<16)|0L); /* # Shdrs & shdr string size */ + } lput(1L); /* text - type = PT_LOAD */ lput(HEADR); /* file offset */ @@ -331,6 +341,56 @@ asmb(void) lput(lcsize); /* line number size */ lput(0x04L); /* protections = R */ lput(0x04L); /* alignment code?? */ + cflush(); + + if(!debug['S']) + break; + + seek(cout, HEADR+textsize+datsize+symsize, 0); + lput(1); /* Section name (string tbl index) */ + lput(1); /* Section type */ + lput(2|4); /* Section flags */ + lput(INITTEXT & ~KMASK); /* Section virtual addr at execution */ + lput(HEADR); /* Section file offset */ + lput(textsize); /* Section size in bytes */ + lput(0); /* Link to another section */ + lput(0); /* Additional section information */ + lput(0x10000L); /* Section alignment */ + lput(0); /* Entry size if section holds table */ + + lput(7); /* Section name (string tbl index) */ + lput(1); /* Section type */ + lput(2|1); /* Section flags */ + lput(INITDAT & ~KMASK); /* Section virtual addr at execution */ + lput(HEADR+textsize); /* Section file offset */ + lput(datsize); /* Section size in bytes */ + lput(0); /* Link to another section */ + lput(0); /* Additional section information */ + lput(0x10000L); /* Section alignment */ + lput(0); /* Entry size if section holds table */ + + /* string section header */ + lput(12); /* Section name (string tbl index) */ + lput(3); /* Section type */ + lput(1 << 5); /* Section flags */ + lput(0); /* Section virtual addr at execution */ + lput(HEADR+textsize+datsize+symsize+3*40); /* Section file offset */ + lput(14); /* Section size in bytes */ + lput(0); /* Link to another section */ + lput(0); /* Additional section information */ + lput(1); /* Section alignment */ + lput(0); /* Entry size if section holds table */ + + /* string table */ + cput(0); + strnput(".text", 5); + cput(0); + strnput(".data", 5); + cput(0); + strnput(".strtab", 7); + cput(0); + cput(0); + break; } cflush(); diff --git a/utils/ql/asmout.c b/utils/ql/asmout.c index e3d96694..96cb3df3 100644 --- a/utils/ql/asmout.c +++ b/utils/ql/asmout.c @@ -942,18 +942,80 @@ oprrr(int a) case AFNMSUBCC: return OPVCC(63,30,0,1); case AFNMSUBS: return OPVCC(59,30,0,0); case AFNMSUBSCC: return OPVCC(59,30,0,1); + case AFRES: return OPVCC(59,24,0,0); + case AFRESCC: return OPVCC(59,24,0,1); case AFRSP: return OPVCC(63,12,0,0); case AFRSPCC: return OPVCC(63,12,0,1); + case AFRSQRTE: return OPVCC(63,26,0,0); + case AFRSQRTECC: return OPVCC(63,26,0,1); + case AFSEL: return OPVCC(63,23,0,0); + case AFSELCC: return OPVCC(63,23,0,1); + case AFSQRT: return OPVCC(63,22,0,0); + case AFSQRTCC: return OPVCC(63,22,0,1); + case AFSQRTS: return OPVCC(59,22,0,0); + case AFSQRTSCC: return OPVCC(59,22,0,1); case AFSUB: return OPVCC(63,20,0,0); case AFSUBCC: return OPVCC(63,20,0,1); case AFSUBS: return OPVCC(59,20,0,0); case AFSUBSCC: return OPVCC(59,20,0,1); + /* fp2 */ + case AFPMUL: return OPVCC(0,8,0,0); + case AFXMUL: return OPVCC(0,9,0,0); + case AFXPMUL: return OPVCC(0,10,0,0); + case AFXSMUL: return OPVCC(0,11,0,0); + case AFPADD: return OPVCC(0,12,0,0); + case AFPSUB: return OPVCC(0,13,0,0); + case AFPRE: return OPVCC(0,14,0,0); + case AFPRSQRTE: return OPVCC(0,15,0,0); + case AFPMADD: return OPVCC(0,16,0,0); + case AFXMADD: return OPVCC(0,17,0,0); + case AFXCPMADD: return OPVCC(0,18,0,0); + case AFXCSMADD: return OPVCC(0,19,0,0); + case AFPNMADD: return OPVCC(0,20,0,0); + case AFXNMADD: return OPVCC(0,21,0,0); + case AFXCPNMADD: return OPVCC(0,22,0,0); + case AFXCSNMADD: return OPVCC(0,23,0,0); + case AFPMSUB: return OPVCC(0,24,0,0); + case AFXMSUB: return OPVCC(0,25,0,0); + case AFXCPMSUB: return OPVCC(0,26,0,0); + case AFXCSMSUB: return OPVCC(0,27,0,0); + case AFPNMSUB: return OPVCC(0,28,0,0); + case AFXNMSUB: return OPVCC(0,29,0,0); + case AFXCPNMSUB: return OPVCC(0,30,0,0); + case AFXCSNMSUB: return OPVCC(0,31,0,0); + case AFMOVPD: return OPVCC(0,32,0,0); /* fpmr, X form */ + case AFPABS: return OPVCC(0,96,0,0); + case AFPNEG: return OPVCC(0,160,0,0); + case AFPRSP: return OPVCC(0,192,0,0); + case AFPNABS: return OPVCC(0,224,0,0); + case AFMOVSD: return OPVCC(0,288,0,0); /* fsmr */ + case AFSCMP: return OPVCC(0,320,0,0)|(3<<21); + case AFSABS: return OPVCC(0,352,0,0); + case AFSNEG: return OPVCC(0,416,0,0); + case AFSNABS: return OPVCC(0,480,0,0); + case AFMOVXD: return OPVCC(0,544,0,0); + case AFPCTIW: return OPVCC(0,576,0,0); + case AFPCTIWZ: return OPVCC(0,704,0,0); + + case AFPMOVD: return OPVCC(0,32,0,0); /* fpmr */ + case AFSMOVD: return OPVCC(0,288,0,0); /* fsmr */ + case AFXMOVD: return OPVCC(0,544,0,0); /* fxmr */ + case AFSMOVP: return OPVCC(0,800,0,0); /* fsmtp */ + case AFPMOVS: return OPVCC(0,928,0,0); /* fsmfp */ + + case AFXCPNPMA: return OPVCC(4,24,0,0); + case AFXCSNPMA: return OPVCC(4,25,0,0); + case AFXCPNSMA: return OPVCC(4,26,0,0); + case AFXCSNSMA: return OPVCC(4,27,0,0); + case AFXCXNPMA: return OPVCC(4,29,0,0); + case AFXCXNSMA: return OPVCC(4,30,0,0); + case AFXCXMA: return OPVCC(4,28,0,0); + case AFXCXNMS: return OPVCC(4,31,0,0); + case AICBI: return OPVCC(31,982,0,0); case AISYNC: return OPVCC(19,150,0,0); - /* lscb etc are not PowerPC instructions */ - case AMTFSB0: return OPVCC(63,70,0,0); case AMTFSB0CC: return OPVCC(63,70,0,1); case AMTFSB1: return OPVCC(63,38,0,0); @@ -1228,6 +1290,18 @@ oploadx(int a) case AECIWX: return OPVCC(31,310,0,0); /* eciwx */ case ALWAR: return OPVCC(31,20,0,0); /* lwarx */ case ALSW: return OPVCC(31,533,0,0); /* lswx */ + case AFMOVSS: return OPVCC(31,142,0,0); /* lfssx */ + case AFMOVSSU: return OPVCC(31,174,0,0); /* lfssux */ + case AFMOVSD: return OPVCC(31,206,0,0); + case AFMOVSDU: return OPVCC(31,238,0,0); + case AFMOVXS: return OPVCC(31,270,0,0); + case AFMOVSXU: return OPVCC(31,302,0,0); + case AFMOVXD: return OPVCC(31,334,0,0); + case AFMOVXDU: return OPVCC(31,366,0,0); + case AFMOVPS: return OPVCC(31,398,0,0); + case AFMOVPSU: return OPVCC(31,430,0,0); + case AFMOVPD: return OPVCC(31,462,0,0); + case AFMOVPDU: return OPVCC(31,494,0,0); } diag("bad loadx opcode %A", a); return 0; @@ -1287,6 +1361,19 @@ opstorex(int a) case AMOVWBR: return OPVCC(31,662,0,0); /* stwbrx */ case ASTWCCC: return OPVCC(31,150,0,1); /* stwcx. */ case AECOWX: return OPVCC(31,438,0,0); /* ecowx */ + case AFMOVSS: return OPVCC(31,654,0,0); +/* case AFMOVSSU: return OPVCC(31,yy,0,0); */ /* stfssux not known */ +/* case AFMOVSD: return OPVCC(31,yy,0,0); */ /* stfsdx not known */ + case AFMOVSDU: return OPVCC(31,750,0,0); + case AFMOVXS: return OPVCC(31,782,0,0); + case AFMOVSXU: return OPVCC(31,814,0,0); + case AFMOVXD: return OPVCC(31,846,0,0); + case AFMOVXDU: return OPVCC(31,878,0,0); + case AFMOVPS: return OPVCC(31,910,0,0); + case AFMOVPSU: return OPVCC(31,942,0,0); + case AFMOVPD: return OPVCC(31,974,0,0); + case AFMOVPDU: return OPVCC(31,1006,0,0); + case AFMOVPIW: return OPVCC(31,526,0,0); /* stfpiwx */ } diag("unknown storex opcode %A", a); return 0; diff --git a/utils/ql/list.c b/utils/ql/list.c index 28578779..04139dfc 100644 --- a/utils/ql/list.c +++ b/utils/ql/list.c @@ -141,7 +141,10 @@ Dconv(Fmt *fp) case D_DCR: if(a->name == D_NONE && a->sym == S) { - sprint(str, "DCR(%ld)", a->offset); + if(a->reg == NREG) + sprint(str, "DCR(%ld)", a->offset); + else + sprint(str, "DCR(R%d)", a->reg); break; } sprint(str, "DCR-GOK(%d)", a->reg); diff --git a/utils/ql/mkfile b/utils/ql/mkfile index 19391282..1296b005 100644 --- a/utils/ql/mkfile +++ b/utils/ql/mkfile @@ -4,14 +4,14 @@ TARG=ql OFILES=\ asm.$O\ + asmout.$O\ list.$O\ + noop.$O\ obj.$O\ optab.$O\ pass.$O\ span.$O\ enam.$O\ - noop.$O\ - asmout.$O\ cnam.$O\ sched.$O\ $TARGMODEL.$O\ @@ -31,3 +31,6 @@ CFLAGS= $CFLAGS -I../include enam.$O: ../qc/enam.c $CC $CFLAGS ../qc/enam.c + +#cnam.c: l.h +# rc mkcname diff --git a/utils/ql/noop.c b/utils/ql/noop.c index abb35057..bc17191e 100644 --- a/utils/ql/noop.c +++ b/utils/ql/noop.c @@ -501,7 +501,7 @@ addnop(Prog *p) Prog *q; q = prg(); - q->as = ANOR; + q->as = AOR; q->line = p->line; q->from.type = D_REG; q->from.reg = REGZERO; diff --git a/utils/ql/obj.c b/utils/ql/obj.c index a4e76c1c..adff8dfd 100644 --- a/utils/ql/obj.c +++ b/utils/ql/obj.c @@ -6,6 +6,9 @@ #define DEFAULT '9' #endif +#define OANAME 229 /* old ANAME */ + + char *noname = "<none>"; char symname[] = SYMDEF; char thechar = 'q'; @@ -718,35 +721,39 @@ loop: bloc = buf.xbuf; goto loop; } - o = bloc[0]; /* as */ + o = bloc[0] | (bloc[1] << 8); /* as */ + if(bloc[0] == OANAME && o != OANAME) { + diag("%s: probably old .q file\n", pn); + errorexit(); + } if(o <= 0 || o >= ALAST) { diag("%s: opcode out of range %d", pn, o); - print(" probably not a .q file\n"); + print(" probably not a .%c file\n", thechar); errorexit(); } if(o == ANAME || o == ASIGNAME) { sig = 0; if(o == ASIGNAME) { - sig = bloc[1] | (bloc[2]<<8) | (bloc[3]<<16) | (bloc[4]<<24); + sig = bloc[2] | (bloc[3]<<8) | (bloc[4]<<16) | (bloc[5]<<24); bloc += 4; c -= 4; } - stop = memchr(&bloc[3], 0, bsize-&bloc[3]); + stop = memchr(&bloc[4], 0, bsize-&bloc[4]); if(stop == 0){ bsize = readsome(f, buf.xbuf, bloc, bsize, c); if(bsize == 0) goto eof; bloc = buf.xbuf; - stop = memchr(&bloc[3], 0, bsize-&bloc[3]); + stop = memchr(&bloc[4], 0, bsize-&bloc[4]); if(stop == 0){ fprint(2, "%s: name too long\n", pn); errorexit(); } } - v = bloc[1]; /* type */ - o = bloc[2]; /* sym */ - bloc += 3; - c -= 3; + v = bloc[2]; /* type */ + o = bloc[3]; /* sym */ + bloc += 4; + c -= 4; r = 0; if(v == D_STATIC) @@ -789,12 +796,12 @@ loop: hunk += sizeof(Prog); p->as = o; - p->reg = bloc[1] & 0x3f; - if(bloc[1] & 0x80) + p->reg = bloc[2] & 0x3f; + if(bloc[2] & 0x80) p->mark = NOSCHED; - p->line = bloc[2] | (bloc[3]<<8) | (bloc[4]<<16) | (bloc[5]<<24); - r = zaddr(bloc+6, &p->from, h) + 6; - if(bloc[1] & 0x40) + p->line = bloc[3] | (bloc[4]<<8) | (bloc[5]<<16) | (bloc[6]<<24); + r = zaddr(bloc+7, &p->from, h) + 7; + if(bloc[2] & 0x40) r += zaddr(bloc+r, &p->from3, h); else p->from3 = zprg.from3; diff --git a/utils/ql/optab.c b/utils/ql/optab.c index 8a9de1bb..57813f7f 100644 --- a/utils/ql/optab.c +++ b/utils/ql/optab.c @@ -206,6 +206,8 @@ Optab optab[] = { AFMOVD, C_FREG, C_NONE, C_NONE, C_LOREG, 7, 4, REGZERO }, { AFMOVD, C_FREG, C_NONE, C_NONE, C_ADDR, 74, 8, 0 }, + { AFPMOVD, C_FREG, C_NONE, C_NONE, C_FREG, 33, 4, 0 }, + { ASYNC, C_NONE, C_NONE, C_NONE, C_NONE, 46, 4, 0 }, { AWORD, C_LCON, C_NONE, C_NONE, C_NONE, 40, 4, 0 }, @@ -285,5 +287,13 @@ Optab optab[] = { AMACCHW, C_REG, C_REG, C_NONE, C_REG, 2, 4, 0 }, /* op rb,ra,rt */ + { AFMOVSS, C_ZOREG, C_REG, C_NONE, C_FREG, 45, 4, 0 }, + { AFMOVSS, C_ZOREG, C_NONE, C_NONE, C_FREG, 45, 4, 0 }, + { AFMOVSS, C_FREG, C_REG, C_NONE, C_ZOREG, 44, 4, 0 }, + { AFMOVSS, C_FREG, C_NONE, C_NONE, C_ZOREG, 44, 4, 0 }, + + { AFMOVPIW, C_FREG, C_REG, C_NONE, C_ZOREG, 44, 4, 0 }, + { AFMOVPIW, C_FREG, C_NONE, C_NONE, C_ZOREG, 44, 4, 0 }, + { AXXX, C_NONE, C_NONE, C_NONE, C_NONE, 0, 4, 0 }, }; diff --git a/utils/ql/span.c b/utils/ql/span.c index b3ae1dd4..4a23f68f 100644 --- a/utils/ql/span.c +++ b/utils/ql/span.c @@ -4,16 +4,19 @@ void span(void) { - Prog *p; + Prog *p, *q; Sym *setext; Optab *o; - int m; - long c; + int m, bflag; + long c, otxt; if(debug['v']) Bprint(&bso, "%5.2f span\n", cputime()); Bflush(&bso); + + bflag = 0; c = INITTEXT; + otxt = c; for(p = firstp; p != P; p = p->link) { p->pc = c; o = oplook(p); @@ -33,6 +36,10 @@ span(void) } if(p->from.sym != S) p->from.sym->value = c; + /* need passes to resolve branches? */ + if(c-otxt >= (1L<<15)) + bflag = c; + otxt = c; continue; } if(p->as != ANOP) @@ -41,7 +48,60 @@ span(void) } c += m; } - c = rnd(c, 4); + + /* + * if any procedure is large enough to + * generate a large SBRA branch, then + * generate extra passes putting branches + * around jmps to fix. this is rare. + */ + while(bflag) { + if(debug['v']) + Bprint(&bso, "%5.2f span1\n", cputime()); + bflag = 0; + c = INITTEXT; + for(p = firstp; p != P; p = p->link) { + p->pc = c; + o = oplook(p); + if((o->type == 16 || o->type == 17) && p->cond) { + otxt = p->cond->pc - c; + if(otxt < -(1L<<16)+10 || otxt >= (1L<<15)-10) { + q = prg(); + q->link = p->link; + p->link = q; + q->as = ABR; + q->to.type = D_BRANCH; + q->cond = p->cond; + p->cond = q; + q = prg(); + q->link = p->link; + p->link = q; + q->as = ABR; + q->to.type = D_BRANCH; + q->cond = q->link->link; + addnop(p->link); + addnop(p); + bflag = 1; + } + } + m = o->size; + if(m == 0) { + if(p->as == ATEXT) { + curtext = p; + autosize = p->to.offset + 4; + if(p->from.sym != S) + p->from.sym->value = c; + continue; + } + if(p->as != ANOP) + diag("zero-width instruction\n%P", p); + continue; + } + c += m; + } + } + + c = rnd(c, 8); setext = lookup("etext", 0); if(setext != S) { @@ -224,8 +284,9 @@ aclass(Adr *a) instoffset = s->value + a->offset + INITDAT; if(dlm) return C_LCON; -/* not sure why this barfs */ -return C_LCON; + /* not sure why this barfs */ + return C_LCON; + /* if(instoffset == 0) return C_ZCON; if(instoffset >= -0x8000 && instoffset <= 0xffff) @@ -233,6 +294,7 @@ return C_LCON; if((instoffset & 0xffff) == 0) return C_UCON; return C_LCON; + */ case D_AUTO: instoffset = autosize + a->offset; @@ -437,6 +499,8 @@ buildop(void) case AECOWX: /* indexed store: op s,(b+a); op s,(b) */ oprange[ASTWCCC] = oprange[r]; break; + case AFMOVPIW: /* indexed floating store */ + break; case AREM: /* macro */ oprange[AREMCC] = oprange[r]; oprange[AREMV] = oprange[r]; @@ -564,11 +628,6 @@ buildop(void) oprange[ANMACLHWV] = oprange[r]; oprange[ANMACLHWVCC] = oprange[r]; break; -/* floating point move *//* - oprange[AFMR] = oprange[r]; - oprange[AFMRCC] = oprange[r]; -*/ -/**/ case AMOVBZ: /* lbz, stz, rlwm(r/r), lhz, lha, stz, and x variants */ oprange[AMOVH] = oprange[r]; oprange[AMOVHZ] = oprange[r]; @@ -647,6 +706,25 @@ buildop(void) oprange[AFCTIWCC] = oprange[r]; oprange[AFCTIWZ] = oprange[r]; oprange[AFCTIWZCC] = oprange[r]; + oprange[AFRES] = oprange[r]; + oprange[AFRESCC] = oprange[r]; + oprange[AFRSQRTE] = oprange[r]; + oprange[AFRSQRTECC] = oprange[r]; + oprange[AFSQRT] = oprange[r]; + oprange[AFSQRTCC] = oprange[r]; + oprange[AFSQRTS] = oprange[r]; + oprange[AFSQRTSCC] = oprange[r]; + oprange[AFPRE] = oprange[r]; + oprange[AFPRSQRTE] = oprange[r]; + oprange[AFPABS] = oprange[r]; + oprange[AFPNEG] = oprange[r]; + oprange[AFPRSP] = oprange[r]; + oprange[AFPNABS] = oprange[r]; + oprange[AFSABS] = oprange[r]; + oprange[AFSNEG] = oprange[r]; + oprange[AFSNABS] = oprange[r]; + oprange[AFPCTIW] = oprange[r]; + oprange[AFPCTIWZ] = oprange[r]; break; case AFADD: oprange[AFADDS] = oprange[r]; @@ -660,6 +738,8 @@ buildop(void) oprange[AFSUBS] = oprange[r]; oprange[AFSUBCC] = oprange[r]; oprange[AFSUBSCC] = oprange[r]; + oprange[AFPADD] = oprange[r]; + oprange[AFPSUB] = oprange[r]; break; case AFMADD: oprange[AFMADDCC] = oprange[r]; @@ -677,11 +757,42 @@ buildop(void) oprange[AFNMSUBCC] = oprange[r]; oprange[AFNMSUBS] = oprange[r]; oprange[AFNMSUBSCC] = oprange[r]; + oprange[AFSEL] = oprange[r]; + oprange[AFSELCC] = oprange[r]; + oprange[AFPSEL] = oprange[r]; + oprange[AFPMADD] = oprange[r]; + oprange[AFXMADD] = oprange[r]; + oprange[AFXCPMADD] = oprange[r]; + oprange[AFXCSMADD] = oprange[r]; + oprange[AFPNMADD] = oprange[r]; + oprange[AFXNMADD] = oprange[r]; + oprange[AFXCPNMADD] = oprange[r]; + oprange[AFXCSNMADD] = oprange[r]; + oprange[AFPMSUB] = oprange[r]; + oprange[AFXMSUB] = oprange[r]; + oprange[AFXCPMSUB] = oprange[r]; + oprange[AFXCSMSUB] = oprange[r]; + oprange[AFPNMSUB] = oprange[r]; + oprange[AFXNMSUB] = oprange[r]; + oprange[AFXCPNMSUB] = oprange[r]; + oprange[AFXCSNMSUB] = oprange[r]; + oprange[AFXCPNPMA] = oprange[r]; + oprange[AFXCSNPMA] = oprange[r]; + oprange[AFXCPNSMA] = oprange[r]; + oprange[AFXCSNSMA] = oprange[r]; + oprange[AFXCXNPMA] = oprange[r]; + oprange[AFXCXNSMA] = oprange[r]; + oprange[AFXCXMA] = oprange[r]; + oprange[AFXCXNMS] = oprange[r]; break; case AFMUL: oprange[AFMULS] = oprange[r]; oprange[AFMULCC] = oprange[r]; oprange[AFMULSCC] = oprange[r]; + oprange[AFPMUL] = oprange[r]; + oprange[AFXMUL] = oprange[r]; + oprange[AFXPMUL] = oprange[r]; + oprange[AFXSMUL] = oprange[r]; break; case AFCMPO: oprange[AFCMPU] = oprange[r]; @@ -734,6 +845,12 @@ buildop(void) oprange[AFMOVS] = oprange[r]; oprange[AFMOVSU] = oprange[r]; break; + case AFPMOVD: + oprange[AFSMOVD] = oprange[r]; + oprange[AFXMOVD] = oprange[r]; + oprange[AFSMOVP] = oprange[r]; + oprange[AFPMOVS] = oprange[r]; + break; case AECIWX: oprange[ALWAR] = oprange[r]; break; @@ -744,6 +861,19 @@ buildop(void) case AMOVHBR: oprange[AMOVWBR] = oprange[r]; break; + case AFMOVSS: /* indexed floating loads and stores (fp2) */ + oprange[AFMOVSSU] = oprange[r]; + oprange[AFMOVSD] = oprange[r]; + oprange[AFMOVSDU] = oprange[r]; + oprange[AFMOVXS] = oprange[r]; + oprange[AFMOVSXU] = oprange[r]; + oprange[AFMOVXD] = oprange[r]; + oprange[AFMOVXDU] = oprange[r]; + oprange[AFMOVPS] = oprange[r]; + oprange[AFMOVPSU] = oprange[r]; + oprange[AFMOVPD] = oprange[r]; + oprange[AFMOVPDU] = oprange[r]; + break; case AADD: case AANDCC: /* and. Rb,Rs,Ra; andi. $uimm,Rs,Ra; andis. $uimm,Rs,Ra */ case ACMP: diff --git a/utils/tc/gc.h b/utils/tc/gc.h index e61a1967..a4135374 100644 --- a/utils/tc/gc.h +++ b/utils/tc/gc.h @@ -267,7 +267,7 @@ void gpseudo(int, Sym*, Node*); int swcmp(const void*, const void*); void doswit(Node*); void swit1(C1*, int, long, Node*); -void cas(void); +void casf(void); void bitload(Node*, Node*, Node*, Node*, Node*); void bitstore(Node*, Node*, Node*, Node*, Node*); long outstring(char*, long); diff --git a/utils/tc/peep.c b/utils/tc/peep.c index e53b0cdd..c94a3e41 100644 --- a/utils/tc/peep.c +++ b/utils/tc/peep.c @@ -635,7 +635,7 @@ copyu(Prog *p, Adr *v, Adr *s) return 3; return 0; } - return 0; + /* not reached */ } int diff --git a/utils/tc/sgen.c b/utils/tc/sgen.c index d76de7de..ea5fba44 100644 --- a/utils/tc/sgen.c +++ b/utils/tc/sgen.c @@ -175,7 +175,7 @@ loop: if(cases == C) diag(n, "case/default outside a switch"); if(l == Z) { - cas(); + casf(); cases->val = 0; cases->def = 1; cases->label = pc; @@ -186,7 +186,7 @@ loop: goto rloop; if(l->op == OCONST) if(typechl[l->type->etype]) { - cas(); + casf(); cases->val = l->vconst; cases->def = 0; cases->label = pc; @@ -210,7 +210,7 @@ loop: cn = cases; cases = C; - cas(); + casf(); sbc = breakpc; breakpc = pc; diff --git a/utils/tc/swt.c b/utils/tc/swt.c index 1ded1e5c..04d879c2 100644 --- a/utils/tc/swt.c +++ b/utils/tc/swt.c @@ -89,7 +89,7 @@ swit1(C1 *q, int nc, long def, Node *n) } void -cas(void) +casf(void) { Case *c; diff --git a/utils/va/lex.c b/utils/va/lex.c index fee14c2f..83b3fb9e 100644 --- a/utils/va/lex.c +++ b/utils/va/lex.c @@ -36,6 +36,10 @@ main(int argc, char *argv[]) p = ARGF(); setinclude(p); break; + case 'L': /* for little-endian mips */ + thechar = '0'; + thestring = "spim"; + break; } ARGEND if(*argv == 0) { print("usage: %ca [-options] file.s\n", thechar); diff --git a/utils/vc/gc.h b/utils/vc/gc.h index c090af40..71aec5c1 100644 --- a/utils/vc/gc.h +++ b/utils/vc/gc.h @@ -257,7 +257,7 @@ void gpseudo(int, Sym*, Node*); int swcmp(const void*, const void*); void doswit(Node*); void swit1(C1*, int, long, Node*, Node*); -void cas(void); +void casf(void); void bitload(Node*, Node*, Node*, Node*, Node*); void bitstore(Node*, Node*, Node*, Node*, Node*); long outstring(char*, long); diff --git a/utils/vc/sgen.c b/utils/vc/sgen.c index e4aa65e0..c0fec8a3 100644 --- a/utils/vc/sgen.c +++ b/utils/vc/sgen.c @@ -154,7 +154,7 @@ loop: if(cases == C) diag(n, "case/default outside a switch"); if(l == Z) { - cas(); + casf(); cases->val = 0; cases->def = 1; cases->label = pc; @@ -165,7 +165,7 @@ loop: goto rloop; if(l->op == OCONST) if(typechl[l->type->etype]) { - cas(); + casf(); cases->val = l->vconst; cases->def = 0; cases->label = pc; @@ -189,7 +189,7 @@ loop: cn = cases; cases = C; - cas(); + casf(); sbc = breakpc; breakpc = pc; diff --git a/utils/vc/swt.c b/utils/vc/swt.c index 0ec09b39..d5c72dc1 100644 --- a/utils/vc/swt.c +++ b/utils/vc/swt.c @@ -93,7 +93,7 @@ swit1(C1 *q, int nc, long def, Node *n, Node *tn) } void -cas(void) +casf(void) { Case *c; |
