Clean up user library include paths (XCC)
[akaros.git] / user / vmm / decode.c
index d717878..afcefb6 100644 (file)
@@ -44,7 +44,11 @@ int debug_decode = 0;
 static char *modrmreg[] = {"rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi"};
 
 // Since we at most have to decode less than half of each instruction, I'm trying to be dumb here.
-// Fortunately, for me, what's not hard.
+// Fortunately, for me, that's not hard.
+// I'm trying to avoid the whole Big Fun of full instruction decode, and in most of these
+// cases we only have to know register, address, operation size, and instruction length.
+// The ugly messiness of the SIB and all that are not yet needed. Maybe they
+// never will be.
 
 // Target size -- 1, 2, 4, or 8 bytes. We have yet to see 64 bytes. 
 // TODO: if we ever see it, test the prefix. Since this only supports the low 1M,
@@ -62,6 +66,10 @@ static int target(void *insn, int *store)
                s = s == 4 ? 2 : 4;
                return s;
        }
+       if (*byte == 0x44) {
+               byte++;
+               word++;
+       }
        switch(*byte) {
        case 0x3a:
        case 0x8a:
@@ -100,6 +108,10 @@ static int target(void *insn, int *store)
        case 0x8b:
        case 0x81:
                *store = !(*byte & 2);
+               break;
+       default:
+               fprintf(stderr, "%s: Can't happen\n", __func__);
+               break;
        }
        return s;
 }
@@ -113,6 +125,12 @@ static int insize(void *rip)
 {
        uint8_t *kva = rip;
        int advance = 3;
+       int extra = 0;
+       if (kva[0] == 0x44) {
+               extra = 1;
+               kva++;
+       }
+
        /* the dreaded mod/rm byte. */
        int mod = kva[1]>>6;
        int rm = kva[1] & 7;
@@ -123,7 +141,7 @@ static int insize(void *rip)
        case 0x0f: 
                break;
        case 0x81:
-               advance = 6;
+               advance = 6 + extra;
                break;
        case 0x3a:
        case 0x8a:
@@ -132,16 +150,16 @@ static int insize(void *rip)
        case 0x8b:
                switch (mod) {
                case 0: 
-                       advance = 2 + (rm == 4);
+                       advance = 2 + (rm == 4) + extra;
                        break;
                case 1:
-                       advance = 3 + (rm == 4);
+                       advance = 3 + (rm == 4) + extra;
                        break;
                case 2: 
-                       advance = 6 + (rm == 4);
+                       advance = 6 + (rm == 4) + extra;
                        break;
                case 3:
-                       advance = 2;
+                       advance = 2 + extra;
                        break;
                }
                break;
@@ -189,12 +207,13 @@ int decode(struct vmctl *v, uint64_t *gpa, uint8_t *destreg, uint64_t **regp, in
        if (*size < 0)
                return -1;
 
-       uint16_t ins = *(uint16_t *)kva;
-       DPRINTF("ins is %04x\n", ins);
-       
        *advance = insize(kva);
 
+       uint16_t ins = *(uint16_t *)(kva + (kva[0] == 0x44));
+       DPRINTF("ins is %04x\n", ins);
+               
        *destreg = (ins>>11) & 7;
+       *destreg += 8*(kva[0] == 0x44);
        // Our primitive approach wins big here.
        // We don't have to decode the register or the offset used
        // in the computation; that was done by the CPU and is the gpa.
@@ -224,6 +243,30 @@ int decode(struct vmctl *v, uint64_t *gpa, uint8_t *destreg, uint64_t **regp, in
        case 7:
                *regp = &v->regs.tf_rdi;
                break;
+       case 8:
+               *regp = &v->regs.tf_r8;
+               break;
+       case 9:
+               *regp = &v->regs.tf_r9;
+               break;
+       case 10:
+               *regp = &v->regs.tf_r10;
+               break;
+       case 11:
+               *regp = &v->regs.tf_r11;
+               break;
+       case 12:
+               *regp = &v->regs.tf_r12;
+               break;
+       case 13:
+               *regp = &v->regs.tf_r13;
+               break;
+       case 14:
+               *regp = &v->regs.tf_r14;
+               break;
+       case 15:
+               *regp = &v->regs.tf_r15;
+               break;
        }
        return 0;
 }