duskos

dusk os fork
git clone git://git.alexwennerberg.com/duskos
Log | Files | Refs | README | LICENSE

dis.c (6025B) - raw


      1 /* Disassembler for the CVM bytecode
      2 
      3 Because of Forth's very dynamic nature, this disassembler can't hope to
      4 disassemble a whole memory space. As soon as we hit a cell or a does, we can't
      5 continue. However, this can be useful to disassemble small pieces of code such
      6 as the ones compiled by the Forth backend of CC.
      7 */
      8 #include <stdio.h>
      9 
     10 
     11 #define ARGNONE 0
     12 #define ARGBYTE 1
     13 #define ARGINT 2
     14 #define ARGFIVE 3  // byte + int
     15 #define ARGOP 4  // byte + ?disp
     16 #define ARGBINOP 5  // opidx + byte + ?disp
     17 #define ARGOPN 6 // op + immediate
     18 #define ARGERR 7   // can't continue, arg size unknown
     19 #define OPHASDISP 0x08
     20 
     21 #define BINOPCNT 0x10
     22 static char* binops[BINOPCNT] = {
     23 	"+", "-", "*", "/", "%", "<<", ">>", "err",
     24 	"&", "|", "^", "err", "err", "err", "err", "err"
     25 };
     26 
     27 struct op {
     28     char *name; // NULL= no op
     29     int arg;
     30 };
     31 
     32 #define OPCNT 0x70
     33 static struct op ops[OPCNT] = {
     34     {"BR", ARGINT},
     35     {"CALL", ARGINT},
     36     {"RET", ARGNONE},
     37     {"BRWR", ARGNONE},
     38     {"BRA", ARGNONE},
     39     {"BRC", ARGFIVE},
     40     {"BRCDROP", ARGFIVE},
     41     {"YIELD", ARGNONE},
     42 
     43     {"PSADD", ARGINT},
     44     {"RSADD", ARGINT},
     45     {"WLIT", ARGINT},
     46     {"ALIT", ARGINT},
     47     {"WADDN", ARGINT},
     48     {"AADDN", ARGINT},
     49     {"W2A", ARGNONE},
     50     {"WSWAPA", ARGNONE},
     51 
     52     {"WFETCH", ARGOP},
     53 	{NULL, ARGERR},
     54     {"WSWAP", ARGOP},
     55     {"MADDN", ARGOPN},
     56     {"WCMP", ARGOP},
     57     {"WIFETCH", ARGOP},
     58     {"WISTORE", ARGOP},
     59     {"WLEA", ARGOP},
     60 
     61     {"WFETCH16", ARGOP},
     62 	{NULL, ARGERR},
     63     {"WSWAP16", ARGOP},
     64     {"MADDN16", ARGOPN},
     65     {"WCMP16", ARGOP},
     66     {"WIFETCH16", ARGOP},
     67     {"WISTORE16", ARGOP},
     68     {"WLEA", ARGOP},
     69 
     70     {"WFETCH8", ARGOP},
     71 	{NULL, ARGERR},
     72     {"WSWAP8", ARGOP},
     73     {"MADDN8", ARGOPN},
     74     {"WCMP8", ARGOP},
     75     {"WIFETCH8", ARGOP},
     76     {"WISTORE8", ARGOP},
     77     {"WLEA", ARGOP},
     78 
     79 	{NULL, ARGERR},
     80     {"BOOTRD", ARGNONE},
     81     {"STDOUT", ARGNONE},
     82     {"MAYBEKEY", ARGNONE},
     83 	{NULL, ARGERR},
     84 	{"MAKEMEM", ARGNONE},
     85 	{"ADDDISP", ARGNONE},
     86 	{NULL, ARGERR},
     87 
     88     {"MAYBEWORD", ARGNONE},
     89     {"WORD", ARGNONE},
     90     {"PARSE", ARGNONE},
     91     {"FIND", ARGNONE},
     92     {"WNF", ARGNONE},
     93     {"FINDMOD", ARGNONE},
     94 	{NULL, ARGERR},
     95 	{NULL, ARGERR},
     96 
     97     {"STACKCHK", ARGNONE},
     98     {"COMPWORD", ARGNONE},
     99     {"RUNWORD", ARGNONE},
    100     {"COMPILING", ARGNONE},
    101     {"STARTCOMP", ARGNONE},
    102     {"STOPCOMP", ARGNONE},
    103     {"RSADDWR", ARGNONE},
    104 	{"COMPOP", ARGNONE},
    105 
    106     {"ALIGN4", ARGNONE},
    107     {"ENTRY", ARGNONE},
    108     {"CODE", ARGNONE},
    109     {"CODE16", ARGNONE},
    110     {"CODE8", ARGNONE},
    111     {"COMPBINOP", ARGNONE},
    112 	{NULL, ARGERR},
    113 	{NULL, ARGERR},
    114 
    115     {"WBINOP", ARGBINOP},
    116     {"WBINOP16", ARGBINOP},
    117     {"WBINOP8", ARGBINOP},
    118     {"DIVMOD", ARGNONE},
    119 	{NULL, ARGERR},
    120     {"LT", ARGNONE},
    121 	{"NEG", ARGNONE},
    122 	{NULL, ARGERR},
    123 
    124     {"BYE", ARGNONE},
    125     {"BYEFAIL", ARGNONE},
    126     {"QUIT", ARGNONE},
    127     {"ABORT_", ARGNONE},
    128     {"DBG", ARGNONE},
    129     {"USLEEP", ARGNONE},
    130 	{NULL, ARGERR},
    131 	{NULL, ARGERR},
    132 
    133 	{NULL, ARGERR},
    134 	{NULL, ARGERR},
    135 	{NULL, ARGERR},
    136 	{NULL, ARGERR},
    137 	{NULL, ARGERR},
    138     {"WCHECKZ", ARGNONE},
    139     {"STOREC", ARGBYTE},
    140 	{"ACHECKZ", ARGNONE},
    141 
    142     {"FCHILD", ARGNONE},
    143     {"FOPEN", ARGNONE},
    144     {"FREADBUF", ARGNONE},
    145     {"FCLOSE", ARGNONE},
    146     {"FINFO", ARGNONE},
    147     {"FITER", ARGNONE},
    148     {NULL, ARGERR},
    149     {"FSEEK", ARGNONE},
    150 
    151     {"MOUNTDRV", ARGNONE},
    152     {"UNMOUNTDRV", ARGNONE},
    153     {"DRVRD", ARGNONE},
    154     {"DRVWR", ARGNONE},
    155 	{NULL, ARGERR},
    156 	{NULL, ARGERR},
    157 	{NULL, ARGERR},
    158 	{NULL, ARGERR},
    159 };
    160 
    161 /* Now this systen below is really fragile. Offsets will change often, and those
    162    have to be maintained. But oh well... */
    163 struct call {
    164     int addr;
    165     char *name;
    166 };
    167 
    168 #define CALLCNT 8
    169 struct call calls[CALLCNT] = {
    170     {0x2e8, "-"},
    171     {0x1760, "dup"},
    172     {0x18a4, "rot"},
    173     {0x18f8, "nip"},
    174     {0x1a94, "!"},
    175     {0x1b18, "@"},
    176     {0x1e54, "execute"},
    177     {0x1e94, "not"},
    178 };
    179 
    180 static int offset = 0;
    181 
    182 int getint() {
    183     int n = 0;
    184     for (int i=0; i<4; i++) {
    185         n |= getchar() << (i*8);
    186     }
    187     offset += 4;
    188     return n;
    189 }
    190 
    191 void printhalop(int n) {
    192 	printf("\t");
    193 	switch (n & 7) {
    194 		case 0: printf("W"); break;
    195 		case 1: printf("A"); break;
    196 		case 2: printf("PSP"); break;
    197 		case 3: printf("RSP"); break;
    198 		case 4: printf("m"); break;
    199 		default: printf("err");
    200 	}
    201 	if (n & 0x10) printf("&");
    202 	if (n & 0x20) printf(">A");
    203 	if (n & 0x40) printf("<>");
    204 }
    205 
    206 int printarg(int arg) { // returns 1 on success, 0 on error
    207     int n;
    208     switch (arg) {
    209         case ARGNONE: break;
    210         case ARGBYTE:
    211             n = getchar();
    212             offset++;
    213             printf("\t%x", n);
    214             break;
    215         case ARGINT:
    216             n = getint();
    217             printf("\t%x", n);
    218             break;
    219         case ARGFIVE:
    220 			printarg(ARGBYTE);
    221 			printarg(ARGINT);
    222             break;
    223         case ARGOP:
    224             n = getchar();
    225             offset++;
    226 			printhalop(n);
    227 			if (n&OPHASDISP) printarg(ARGINT);
    228 			break;
    229         case ARGBINOP:
    230             n = getchar();
    231             offset++;
    232             printf("\t%s", binops[n]);
    233 			printarg(ARGOP);
    234 			break;
    235         case ARGOPN:
    236 			printarg(ARGOP);
    237 			printarg(ARGINT);
    238             break;
    239         case ARGERR:
    240             fprintf(stderr, "Can't parse this op's arg\n");
    241             return 0;
    242         default:
    243             fprintf(stderr, "Something's wrong\n");
    244             return 0;
    245     }
    246     return 1;
    247 }
    248 
    249 int printcall() {
    250     int addr = getint();
    251     for (int i=0; i<CALLCNT; i++) {
    252         if (calls[i].addr == addr) {
    253             printf("\t%s", calls[i].name);
    254             return 1;
    255         }
    256     }
    257     printf("\t%x", addr);
    258     return 1;
    259 }
    260 
    261 int main() {
    262     int c = getchar();
    263     while (c != EOF) {
    264         printf("%08x ", offset++);
    265         if ((c >= OPCNT) || (ops[c].name == NULL)) {
    266             fprintf(stderr, "Invalid opcode %x\n", c);
    267             return 1;
    268         }
    269         fputs(ops[c].name, stdout);
    270         if (c == 1) { // 1 == CALL
    271             if (!printcall()) return 1;
    272         } else {
    273             if (!printarg(ops[c].arg)) return 1;
    274         }
    275         putchar('\n');
    276         c = getchar();
    277     }
    278 }