]> git.lizzy.rs Git - plan9front.git/blobdiff - sys/src/libmach/5db.c
marshal(1): fix example: upas/mail -> mail (thanks fulton)
[plan9front.git] / sys / src / libmach / 5db.c
index e490d11a69510f5bd9abede27972701dd3e11233..1bd661423b60942e44eb927638fb452b7d377a21 100644 (file)
@@ -61,7 +61,7 @@ static        int     arminstlen(Map*, uvlong);
  */
 Machdata armmach =
 {
-       {0x70, 0x00, 0x20, 0xD1},               /* break point */       /* D1200070 */
+       {0x70, 0x00, 0x20, 0xE1},               /* break point */       /* E1200070 */
        4,                      /* break point size */
 
        leswab,                 /* short to local byte order */
@@ -93,7 +93,7 @@ armexcep(Map *map, Rgetter rget)
        case 0x13:
                return "SVC/SWI Exception";
        case 0x17:
-               return "Prefetch Abort/Data Abort";
+               return "Prefetch Abort/Breakpoint";
        case 0x18:
                return "Data Abort";
        case 0x1b:
@@ -135,11 +135,21 @@ char*     addsub[2] =
 int
 armclass(long w)
 {
-       int op, done;
+       int op, done, cp;
 
        op = (w >> 25) & 0x7;
        switch(op) {
        case 0: /* data processing r,r,r */
+               if((w & 0x0ff00080) == 0x01200000) {
+                       op = (w >> 4) & 0x7;
+                       if(op == 7)
+                               op = 124;       /* bkpt */
+                       else if (op > 0 && op < 4)
+                               op += 124;      /* bx, blx */
+                       else
+                               op = 92;        /* unk */
+                       break;
+               }
                op = ((w >> 4) & 0xf);
                if(op == 0x9) {
                        op = 48+16;             /* mul, swp or *rex */
@@ -175,7 +185,7 @@ armclass(long w)
                if(w & (1<<4))
                        op += 32;
                else
-               if((w & (31<<7)) || (w & (1<<5)))
+               if(w & (31<<7 | 3<<5))
                        op += 16;
                break;
        case 1: /* data processing i,r,r */
@@ -220,8 +230,63 @@ armclass(long w)
                op = (48+24+4+4+2) + ((w >> 24) & 0x1);
                break;
        case 7: /* coprocessor crap */
+               cp = (w >> 8) & 0xF;
+               if(cp == 10 || cp == 11){       /* vfp */
+                       if((w >> 4) & 0x1){
+                               /* vfp register transfer */
+                               switch((w >> 21) & 0x7){
+                               case 0:
+                                       op = 118 + ((w >> 20) & 0x1);
+                                       break;
+                               case 7:
+                                       op = 118+2 + ((w >> 20) & 0x1);
+                                       break;
+                               default:
+                                       op = (48+24+4+4+2+2+4+4);
+                                       break;
+                               }
+                               break;
+                       }
+                       /* vfp data processing */
+                       if(((w >> 23) & 0x1) == 0){
+                               op = 100 + ((w >> 19) & 0x6) + ((w >> 6) & 0x1);
+                               break;
+                       }
+                       switch(((w >> 19) & 0x6) + ((w >> 6) & 0x1)){
+                       case 0:
+                               op = 108;
+                               break;
+                       case 7:
+                               if(((w >> 19) & 0x1) == 0){
+                                       if(((w >> 17) & 0x1) == 0)
+                                               op = 109 + ((w >> 16) & 0x4) +
+                                                       ((w >> 15) & 0x2) +
+                                                       ((w >> 7) & 0x1);
+                                       else if(((w >> 16) & 0x7) == 0x7)
+                                               op = 117;
+                               }
+                               else
+                                       switch((w >> 16) & 0x7){
+                                       case 0:
+                                       case 4:
+                                       case 5:
+                                               op = 117;
+                                               break;
+                                       }
+                               break;
+                       }
+                       if(op == 7)
+                               op = (48+24+4+4+2+2+4+4);
+                       break;
+               }
                op = (48+24+4+4+2+2) + ((w >> 3) & 0x2) + ((w >> 20) & 0x1);
                break;
+       case 6: /* vfp load / store */
+               if(((w >> 21) &0x9) == 0x8){
+                       op = 122 + ((w >> 20) & 0x1);
+                       break;
+               }
+               /* fall through */
        default:          
                op = (48+24+4+4+2+2+4+4);
                break;
@@ -298,7 +363,7 @@ plocal(Instr *i)
  * Print value v as name[+offset]
  */
 static int
-gsymoff(char *buf, int n, long v, int space)
+gsymoff(char *buf, int n, ulong v, int space)
 {
        Symbol s;
        int r;
@@ -351,6 +416,16 @@ armdps(Opcode *o, Instr *i)
                        return;
                }
        }
+       if(i->rd == 15) {
+               if(i->op == 120) {
+                       format("MOVW", i, "PSR, %x");
+                       return;
+               } else 
+               if(i->op == 121) {
+                       format("MOVW", i, "%x, PSR");
+                       return;
+               }
+       }
        format(o->o, i, o->a);
 }
 
@@ -405,12 +480,26 @@ armsdti(Opcode *o, Instr *i)
        format(o->o, i, o->a);
 }
 
+static void
+armvstdi(Opcode *o, Instr *i)
+{
+       ulong v;
+
+       v = (i->w & 0xff) << 2;
+       if(!(i->w & (1<<23)))
+               v = -v;
+       i->imm = v;
+       i->rn = (i->w >> 16) & 0xf;
+       i->rd = (i->w >> 12) & 0xf;
+       format(o->o, i, o->a);
+}
+
 /* arm V4 ld/st halfword, signed byte */
 static void
 armhwby(Opcode *o, Instr *i)
 {
        i->store = ((i->w >> 23) & 0x2) | ((i->w >>21) & 0x1);
-       i->imm = (i->w & 0xf) | ((i->w >> 8) & 0xf);
+       i->imm = (i->w & 0xf) | ((i->w >> 4) & 0xf0);
        if (!(i->w & (1 << 23)))
                i->imm = - i->imm;
        i->rn = (i->w >> 16) & 0xf;
@@ -471,6 +560,13 @@ armb(Opcode *o, Instr *i)
        format(o->o, i, o->a);
 }
 
+static void
+armbpt(Opcode *o, Instr *i)
+{
+       i->imm = ((i->w >> 4) & 0xfff0) | (i->w &0xf);
+       format(o->o, i, o->a);
+}
+
 static void
 armco(Opcode *o, Instr *i)             /* coprocessor instructions */
 {
@@ -523,7 +619,7 @@ armcondpass(Map *map, Rgetter rget, uchar cond)
        case 10:        return n == v;
        case 11:        return n != v;
        case 12:        return !z && (n == v);
-       case 13:        return z && (n != v);
+       case 13:        return z || (n != v);
        case 14:        return 1;
        case 15:        return 0;
        }
@@ -584,11 +680,11 @@ armshiftval(Map *map, Rgetter rget, Instr *i)
                        }
                        return ROR(v, s);
                case 7:                                 /* RORREG */
-                       sprint(buf, "R%ld", (s>>1)&0xF);
-                       s = rget(map, buf);
-                       if(s == 0 || (s & 0xF) == 0)
+                       sprint(buf, "R%ld", s >> 1);
+                       s = rget(map, buf) & 0x1F;
+                       if(s == 0)
                                return v;
-                       return ROR(v, s & 0xF);
+                       return ROR(v, s);
                }
        }
 }
@@ -689,6 +785,19 @@ armfadd(Map *map, Rgetter rget, Instr *i, uvlong pc)
        return rget(map, buf) + armshiftval(map, rget, i);
 }
 
+static uvlong
+armfbx(Map *map, Rgetter rget, Instr *i, uvlong pc)
+{
+       char buf[8];
+       int r;
+
+       if(!armcondpass(map, rget, (i->w>>28)&0xf))
+               return pc+4;
+       r = (i->w >> 0) & 0xf;
+       sprint(buf, "R%d", r);
+       return rget(map, buf);
+}
+
 static uvlong
 armfmovm(Map *map, Rgetter rget, Instr *i, uvlong pc)
 {
@@ -821,9 +930,9 @@ static Opcode opcodes[] =
        "SWPB",         armdpi, 0,      "R%s,(R%n),R%d",
 
 /* 48+16+4 */
-       "MOV%u%C%p",    armhwby, 0,     "R%d,(R%n%UR%M)",
+       "MOV%u%C%p",    armhwby, 0,     "R%d,(R%n%UR%s)",
        "MOV%u%C%p",    armhwby, 0,     "R%d,%I",
-       "MOV%u%C%p",    armhwby, armfmov,       "(R%n%UR%M),R%d",
+       "MOV%u%C%p",    armhwby, armfmov,       "(R%n%UR%s),R%d",
        "MOV%u%C%p",    armhwby, armfmov,       "%I,R%d",
 
 /* 48+24 */
@@ -870,6 +979,46 @@ static Opcode opcodes[] =
 
 /* 99 */
        "RFEV7%P%a",    armbdt, 0,      "(R%n)",
+
+/* 100 */
+       "MLA%f%C",      armdps, 0,      "F%s,F%n,F%d",
+       "MLS%f%C",      armdps, 0,      "F%s,F%n,F%d",
+       "NMLS%f%C",     armdps, 0,      "F%s,F%n,F%d",
+       "NMLA%f%C",     armdps, 0,      "F%s,F%n,F%d",
+       "MUL%f%C",      armdps, 0,      "F%s,F%n,F%d",
+       "NMUL%f%C",     armdps, 0,      "F%s,F%n,F%d",
+       "ADD%f%C",      armdps, 0,      "F%s,F%n,F%d",
+       "SUB%f%C",      armdps, 0,      "F%s,F%n,F%d",
+       "DIV%f%C",      armdps, 0,      "F%s,F%n,F%d",
+
+/* 109 */
+       "MOV%f%C",      armdps, 0,      "F%s,F%d",
+       "ABS%f%C",      armdps, 0,      "F%s,F%d",
+       "NEG%f%C",      armdps, 0,      "F%s,F%d",
+       "SQRT%f%C",     armdps, 0,      "F%s,F%d",
+       "CMP%f%C",      armdps, 0,      "F%s,F%d",
+       "CMPE%f%C",     armdps, 0,      "F%s,F%d",
+       "CMP%f%C",      armdps, 0,      "$0.0,F%d",
+       "CMPE%f%C",     armdps, 0,      "$0.0,F%d",
+
+/* 117 */
+       "MOV%F%R%C",    armdps, 0,      "F%s,F%d",
+
+/* 118 */
+       "MOVW%C",       armdps, 0,      "R%d,F%n",
+       "MOVW%C",       armdps, 0,      "F%n,R%d",
+       "MOVW%C",       armdps, 0,      "R%d,%x",
+       "MOVW%C",       armdps, 0,      "%x,R%d",
+
+/* 122 */
+       "MOV%f%C",      armvstdi,       0,      "F%d,%I",
+       "MOV%f%C",      armvstdi,       0,      "%I,F%d",
+
+/* 124 */
+       "BKPT%C",       armbpt,         0,      "$#%i",
+       "BX%C",         armdps,         armfbx, "(R%s)",
+       "BXJ%C",        armdps,         armfbx, "(R%s)",
+       "BLX%C",        armdps,         armfbx, "(R%s)",
 };
 
 static void
@@ -939,7 +1088,10 @@ format(char *mnemonic, Instr *i, char *f)
                        break;
                                
                case 'm':
-                       bprint(i, "%lud", (i->w>>7) & 0x1f);
+                       n = (i->w>>7) & 0x1f;
+                       if (n == 0 && (i->w & (3<<5)) != 0)
+                               n = 32;
+                       bprint(i, "%d", n);
                        break;
 
                case 'h':
@@ -1011,7 +1163,7 @@ format(char *mnemonic, Instr *i, char *f)
 
                case 'b':
                        i->curr += symoff(i->curr, i->end-i->curr,
-                               i->imm, CTEXT);
+                               (ulong)i->imm, CTEXT);
                        break;
 
                case 'g':
@@ -1019,6 +1171,68 @@ format(char *mnemonic, Instr *i, char *f)
                                i->imm, CANY);
                        break;
 
+               case 'f':
+                       switch((i->w >> 8) & 0xF){
+                       case 10:
+                               bprint(i, "F");
+                               break;
+                       case 11:
+                               bprint(i, "D");
+                               break;
+                       }
+                       break;
+
+               case 'F':
+                       switch(((i->w >> 15) & 0xE) + ((i->w >> 8) & 0x1)){
+                       case 0x0:
+                               bprint(i, ((i->w >> 7) & 0x1)? "WF" : "WF.U");
+                               break;
+                       case 0x1:
+                               bprint(i, ((i->w >> 7) & 0x1)? "WD" : "WD.U");
+                               break;
+                       case 0x8:
+                               bprint(i, "FW.U");
+                               break;
+                       case 0x9:
+                               bprint(i, "DW.U");
+                               break;
+                       case 0xA:
+                               bprint(i, "FW");
+                               break;
+                       case 0xB:
+                               bprint(i, "DW");
+                               break;
+                       case 0xE:
+                               bprint(i, "FD");
+                               break;
+                       case 0xF:
+                               bprint(i, "DF");
+                               break;
+                       }
+                       break;
+
+               case 'R':
+                       if(((i->w >> 7) & 0x1) == 0)
+                               bprint(i, "R");
+                       break;
+
+               case 'x':
+                       switch(i->rn){
+                       case 0:
+                               bprint(i, "FPSID");
+                               break;
+                       case 1:
+                               bprint(i, "FPSCR");
+                               break;
+                       case 2:
+                               bprint(i, "FPEXC");
+                               break;
+                       default:
+                               bprint(i, "FPS(%d)", i->rn);
+                               break;
+                       }
+                       break;
+
                case 'r':
                        n = i->imm&0xffff;
                        j = 0;