asm: more imports
[awish.git] / tools / disasm.bob
blob7df32175148c43e1d28db0ad9b557c09a88bdd25
1 #!/usr/bin/bob
2 /* coded by Ketmar // Vampire Avalon (psyc://ketmar.no-ip.org/~Ketmar)
3  * Understanding is not required. Only obedience.
4  *
5  * This program is free software. It comes without any warranty, to
6  * the extent permitted by applicable law. You can redistribute it
7  * and/or modify it under the terms of the Do What The Fuck You Want
8  * To Public License, Version 2, as published by Sam Hocevar. See
9  * http://sam.zoy.org/wtfpl/COPYING for more details. */
12 define abort (msg) {
13   writeln("ERROR: ", msg);
14   quit(1);
18 LB_GVAR = 0;
19 LB_TVAR = 1;
20 LB_SVAR = 2;
21 LB_CODE = 3;
22 LB_CONST = 4;
25 opnames = \[
26   "add",
27   "sub",
28   "mul",
29   "div",
30   "mod",
31   "bor",
32   "xor",
33   "and",
35   "jeq",
36   "jne",
37   "jlt",
38   "jle",
39   "jgt",
40   "jge",
42   "jmp",
44   "bsr",
46   "brk",
47   "end",
48   "new",
50   "set",
51   "get",
53   "psh",
54   "pop",
55   "swp",
56   "pck",
57   "rol",
58   "dpt",
60   "tid",
61   "kil",
62   "sus",
63   "res",
64   "sta",
66   "rxc",
67   "wxc",
69   "ret",
71   "rst",
73   "mgf",
74   "mgb",
75   "msf",
76   "msb",
80 define isBranch (mnemo) {
81   switch (mnemo) {
82     case "jmp":
83     case "bsr":
84     case "jeq":
85     case "jne":
86     case "jlt":
87     case "jle":
88     case "jgt":
89     case "jge":
90       return true;
91   }
92   return false;
96 fl = new File(args.length<1?"awish.vmd":args[0], "rb");
97 if (!fl) abort("no code file");
98 sign = fl.readBuf(4);
99 if (sign != "AVM1") abort("invalid code file");
100 csize = fl.readWord()^0x2a2a; // code size
101 rcnt = fl.readWord()^0x2a2a; // number of fixups
102 elcnt = fl.readWord()^0x2a2a; // number of extern labels
103 lcnt = fl.readWord()^0x2a2a; // number of labels
104 writeln("code: %d bytes, %d public labels, %d relocations, %d externs".format(csize, lcnt, rcnt, elcnt));
105 code = fl.readBuf(csize);
106 for (local f = 0; f < code.length; ++f) code[f] ^= 0x2a;
107 fl.close();
110 define findLabel (val, type) {
111   /*
112   foreach (local l with list.items()) {
113     if (l.type == type && l.value == val) return l.name;
114   }
115   */
116   return nil;
120 pc = 0;
121 while (pc < code.length) {
122   local opcode = code[pc++], argc, brn, name;
123   //
124   argc = (opcode>>6)&0x03;
125   opcode &= 0x3f;
126   if (opcode >= opnames.length) {
127     write("%04x: BAD".format(pc-1));
128     name = "BAD";
129   } else if (opnames[opcode] == "jmp" && argc == 0) {
130     write("%04x: %s".format(pc-1, "ret"));
131     name = opnames[opcode];
132   } else {
133     write("%04x: %s".format(pc-1, opnames[opcode]));
134     name = opnames[opcode];
135   }
136   brn = isBranch(name);
137   // read operands
138   for (local f = 0; f < argc; ++f) {
139     local vn = code[pc++], val, var = 0, name;
140     //
141     if (f != 0) write(", "); else write(" ");
142     if (vn == 255) {
143       // immediate
144       val = code[pc++];
145       val |= (code[pc++]<<8);
146       if ((f != 00 || !brn) && val >= 32768) val -= 65536;
147       if (brn && f == 0) {
148         name = findLabel(val, LB_CODE);
149         if (name) write(name); else write("0x%04x".format(val));
150       } else {
151         //name = findLabel(val, LB_CONST);
152         name = nil;
153         if (name) write(name); else write(val);
154       }
155     } else if (vn == 127) {
156       // stack
157       val = code[pc++];
158       val |= (code[pc++]<<8);
159       if (val >= 32768) val -= 65536;
160       write("[.", val, "]");
161     } else {
162       // variable
163       if (vn >= 0x80) {
164         // global
165         var = 1;
166         val = vn&0x7f;
167         name = findLabel(val, LB_GVAR);
168         if (name) write("[", name, "]"); else write("[@", val, "]");
169       } else {
170         // thread
171         var = 2;
172         val = vn&0x7f;
173         name = findLabel(val, LB_TVAR);
174         if (name) write("[", name, "]"); else write("[", val, "]");
175       }
176     }
177   }
178   writeln();