diff options
Diffstat (limited to 'utils/libmach')
34 files changed, 3414 insertions, 2404 deletions
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]; |
