History

Moved the Instruction class into the opcodes module. Moved the read* functions into the new utils module. Created an Instruction subclass for each instruction, placing the corresponding opcode value inside it.

David Boddie committed 9 years ago

Commit b833c111 parent 48fa6014 files · +952 −354Browse files

Unified · Split

4 files
  1. dis.py +3 −177
  2. docs/notes.txt +43 −0
  3. opcodes.py +808 −177
  4. utils.py +98 −0
dis.py+3−177
@@ -18,88 +18,12 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. · 17 unmodified lines
1818 from struct import calcsize, pack, unpack
1919
2020 import opcodes
21+from utils import _read, read_B, read_C, read_OP, read_F, read_L, read_P, \
22+ read_W
2123
2224 XMAGIC = 0x0c8030
2325 SMAGIC = 0x0e1722
2426
25−def _read(f, format):
26−
27− size = calcsize(format)
28− return unpack(format, f.read(size))[0]
29−
30−def read_B(f):
31− # byte, 8-bit unsigned
32− return unpack(">B", f.read(1))[0]
33−
34−def read_OP(f):
35−
36− s = f.read(1)
37− v = unpack(">B", s)[0]
38−
39− encoding = v & 0xc0
40−
41− if encoding == 0x80:
42− s += f.read(1)
43− v = unpack(">H", s)[0] & 0x3fff
44− if v >= 0x2000:
45− v = v - 0x4000
46−
47− elif encoding == 0xc0:
48− s += f.read(3)
49− v = unpack(">I", s)[0] & 0x3fffffff
50− if v >= 0x20000000:
51− v = v - 0x40000000
52− else:
53− # The top bit is clear, the next-to-top bit can be 0 or 1.
54− # -64 (0xc0) <= original value <= 63 (0x2f)
55− # -64 (0x40) <= encoded value <= 63 (0x2f)
56− if encoding != 0:
57− # The next-to-top bit is set meaning that
58− # -64 <= original value <= -1
59− v = v - 0x80
60−
61− return v
62−
63−def read_W(f):
64− # 32-bit word
65− return unpack(">i", f.read(4))[0]
66−
67−def read_F(f):
68− # 64-bit float
69− return unpack(">d", f.read(8))[0]
70−
71−def read_L(f):
72− # 64-bit big integer
73− # Signed or unsigned? Assume signed for now.
74− return unpack(">q", f.read(8))[0]
75−
76−def read_P(f):
77− # 32-bit pointer
78− return unpack(">I", f.read(4))[0]
79−
80−def read_C(f):
81− # UTF-8 encoded string
82− s = ""
83− while True:
84− c = f.read(1)
85− if c == "\x00":
86− break
87− s += c
88−
89− return s
90−
91−def read_SO(f):
92−
93− return unpack(">H", f.read(2))[0]
94−
95−def read_SI(f):
96−
97− return unpack(">h", f.read(2))[0]
98−
99−def read_LO(f):
100−
101− return unpack(">i", f.read(4))[0]
102−
10327
10428 class DisError(Exception):
10529 pass
@@ -167,7 +91,7 @@ class Dis: · 61 unmodified lines
16791 i = 0
16892
16993 while i < self.code_size:
170− self.code.append(Instruction(f))
94+ self.code.append(opcodes.Instruction().read(f))
17195 i += 1
17296
17397 def read_types(self, f):
@@ -291,104 +215,6 @@ class RuntimeFlag: · 117 unmodified lines
291215 return self.value & flags != 0
292216
293217
294−class Instruction:
295−
296− def __init__(self, f):
297−
298− self.opcode = read_B(f)
299− self.address_mode = read_B(f)
300−
301− middle = self.address_mode & 0xc0
302− self.middle, self.middle_type = self.read_middle_operand(middle, f)
303−
304− source = (self.address_mode & 0x38) >> 3
305− self.source, self.source_type = self.read_operand(source, f)
306−
307− destination = self.address_mode & 0x07
308− self.destination, self.destination_type = self.read_operand(destination, f)
309−
310− def read_operand(self, operand, f):
311−
312− # Since we shift the address flags for the source operand, we can
313− # check both source and destination operands using the same values.
314−
315− if operand == 0x00:
316− operand = read_OP(f)
317− operand_type = "LO(MP)"
318− elif operand == 0x01:
319− operand = read_OP(f)
320− operand_type = "LO(FP)"
321− elif operand == 0x02:
322− operand = read_OP(f)
323− operand_type = "$OP"
324−
325− # No operand for 0x03.
326−
327− elif operand == 0x04:
328− operand = (read_OP(f), read_OP(f))
329− operand_type = "SO(SO(MP))"
330− elif operand == 0x05:
331− operand = (read_OP(f), read_OP(f))
332− operand_type = "SO(SO(FP))"
333− else:
334− operand = None
335− operand_type = None
336−
337− return operand, operand_type
338−
339− def read_middle_operand(self, operand, f):
340−
341− # The middle operand bits are not shifted.
342−
343− if operand == 0x40:
344− operand = read_OP(f)
345− operand_type = "$SI"
346− elif operand == 0x80:
347− operand = read_OP(f)
348− operand_type = "SO(FP)"
349− elif operand == 0xc0:
350− operand = read_OP(f)
351− operand_type = "SO(MP)"
352− else:
353− operand = None
354− operand_type = None
355−
356− return operand, operand_type
357−
358− def __repr__(self):
359−
360− try:
361− name = opcodes.names[self.opcode]
362− except IndexError:
363− name = hex(self.opcode)
364−
365− operands = []
366− comments = []
367−
368− for op, optype in (self.source, self.source_type), \
369− (self.middle, self.middle_type), \
370− (self.destination, self.destination_type):
371−
372− if optype == "$SI":
373− operands.append("$%x" % op)
374− elif optype == "SO(FP)":
375− operands.append("%i(fp)" % op)
376− elif optype == "SO(MP)":
377− operands.append("%i(mp)" % op)
378− elif optype == "LO(MP)":
379− operands.append("%i(mp)" % op)
380− elif optype == "LO(FP)":
381− operands.append("%i(fp)" % op)
382− elif optype == "$OP":
383− operands.append("$%x" % op)
384− elif optype == "SO(SO(MP))":
385− operands.append("%i(%i(mp))" % op)
386− elif optype == "SO(SO(FP))":
387− operands.append("%i(%i(fp))" % op)
388−
389− return name + " " + ", ".join(operands)
390−
391−
392218 class Type:
393219
394220 def __init__(self, f):
docs/notes.txt+43−0
@@ -0,0 +1,43 @@
1+Function signatures will be output by the Limbo compiler if you pass it the
2+"-D S" debug option.
3+
4+For example, the Sys->print function has this summary output for it:
5+
6+ signed Sys->print type fn(s: string, *): int len 6 sig 0xac849033
7+
8+The type "fn(s: string, *): int" is how the function is declared in the
9+module/sys.m file.
10+
11+Function signatures are generated by the sign function in the limbo/types.c
12+file. We add the debug code after the md5 function call:
13+
14+ md5(sig, sigend, md5sig, nil);
15+ if(debug['S']) {
16+ print("sign %D len %d\n", d, sigend);
17+ print("%s\n", (char*)sig);
18+ }
19+
20+This results in the following additional two debug lines:
21+
22+ sign Sys->print len 6
23+ f*(s)i
24+
25+The "f*(s)i" string is the function signature that needs to be hashed using the
26+MD5 algorithm. Additionally, the following code is used to reduce the hash
27+value to four bytes:
28+
29+ for(i = 0; i < MD5dlen; i += 4)
30+ t->sig ^= md5sig[i+0] | (md5sig[i+1]<<8) | (md5sig[i+2]<<16) | (md5sig[i+3]<<24);
31+
32+We can reproduce this in Python using the md5 module, obtaining the hash value
33+then combining each eight digit segment of it using XOR, before reversing the
34+endianness of the resulting value:
35+
36+ import md5
37+ h = md5.md5("f*(s)i").hexdigest()
38+ l = map(lambda x: int(h[x:x+2], 16), range(0, 32, 2))
39+ hd = sum(map(lambda x: reduce(lambda y, z: y ^ z, l[x::4]) << (x * 8), range(4)))
40+
41+The rtsign and idsign functions in the limbo/types.c file are responsible for
42+creating a signature for a function. The sigkind array contains the characters
43+used for each type of object that will be serialised.
opcodes.py+808−177
@@ -15,183 +15,11 @@ You should have received a copy of the GNU General Public License · 14 unmodified lines
1515 along with this program. If not, see <http://www.gnu.org/licenses/>.
1616 """
1717
18−nop = 0x00
19−alt = 0x01
20−nbalt = 0x02
21−goto = 0x03
22−call = 0x04
23−frame = 0x05
24−spawn = 0x06
25−runt = 0x07
26−load = 0x08
27−mcall = 0x09
28−mspawn = 0x0a
29−mframe = 0x0b
30−ret = 0x0c
31−jmp = 0x0d
32−case = 0x0e
33−exit = 0x0f
34−new = 0x10
35−newa = 0x11
36−newcb = 0x12
37−newcw = 0x13
38−newcf = 0x14
39−newcp = 0x15
40−newcm = 0x16
41−newcmp = 0x17
42−send = 0x18
43−recv = 0x19
44−consb = 0x1a
45−consw = 0x1b
46−consp = 0x1c
47−consf = 0x1d
48−consm = 0x1e
49−consmp = 0x1f
50−headb = 0x20
51−headw = 0x21
52−headp = 0x22
53−headf = 0x23
54−headm = 0x24
55−headmp = 0x25
56−tail = 0x26
57−lea = 0x27
58−indx = 0x28
59−movp = 0x29
60−movm = 0x2a
61−movmp = 0x2b
62−movb = 0x2c
63−movw = 0x2d
64−movf = 0x2e
65−cvtbw = 0x2f
66−cvtwb = 0x30
67−cvtfw = 0x31
68−cvtwf = 0x32
69−cvtca = 0x33
70−cvtac = 0x34
71−cvtwc = 0x35
72−cvtcw = 0x36
73−cvtfc = 0x37
74−cvtcf = 0x38
75−addb = 0x39
76−addw = 0x3a
77−addf = 0x3b
78−subb = 0x3c
79−subw = 0x3d
80−subf = 0x3e
81−mulb = 0x3f
82−mulw = 0x40
83−mulf = 0x41
84−divb = 0x42
85−divw = 0x43
86−divf = 0x44
87−modw = 0x45
88−modb = 0x46
89−andb = 0x47
90−andw = 0x48
91−orb = 0x49
92−orw = 0x4a
93−xorb = 0x4b
94−xorw = 0x4c
95−shlb = 0x4d
96−shlw = 0x4e
97−shrb = 0x4f
98−shrw = 0x50
99−insc = 0x51
100−indc = 0x52
101−addc = 0x53
102−lenc = 0x54
103−lena = 0x55
104−lenl = 0x56
105−beqb = 0x57
106−bneb = 0x58
107−bltb = 0x59
108−bleb = 0x5a
109−bgtb = 0x5b
110−bgeb = 0x5c
111−beqw = 0x5d
112−bnew = 0x5e
113−bltw = 0x5f
114−blew = 0x60
115−bgtw = 0x61
116−bgew = 0x62
117−beqf = 0x63
118−bnef = 0x64
119−bltf = 0x65
120−blef = 0x66
121−bgtf = 0x67
122−bgef = 0x68
123−beqc = 0x69
124−bnec = 0x6a
125−bltc = 0x6b
126−blec = 0x6c
127−bgtc = 0x6d
128−bgec = 0x6e
129−slicea = 0x6f
130−slicela = 0x70
131−slicec = 0x71
132−indw = 0x72
133−indf = 0x73
134−indb = 0x74
135−negf = 0x75
136−movl = 0x76
137−addl = 0x77
138−subl = 0x78
139−divl = 0x79
140−modl = 0x7a
141−mull = 0x7b
142−andl = 0x7c
143−orl = 0x7d
144−xorl = 0x7e
145−shll = 0x7f
146−shrl = 0x80
147−bnel = 0x81
148−bltl = 0x82
149−blel = 0x83
150−bgtl = 0x84
151−bgel = 0x85
152−beql = 0x86
153−cvtlf = 0x87
154−cvtfl = 0x88
155−cvtlw = 0x89
156−cvtwl = 0x8a
157−cvtlc = 0x8b
158−cvtcl = 0x8c
159−headl = 0x8d
160−consl = 0x8e
161−newcl = 0x8f
162−casec = 0x90
163−indl = 0x91
164−movpc = 0x92
165−tcmp = 0x93
166−mnewz = 0x94
167−cvtrf = 0x95
168−cvtfr = 0x96
169−cvtws = 0x97
170−cvtsw = 0x98
171−lsrw = 0x99
172−lsrl = 0x9a
173−eclr = 0x9b
174−newz = 0x9c
175−newaz = 0x9d
176−raise_ = 0x9e
177−casel = 0x9f
178−mulx = 0xa0
179−divx = 0xa1
180−cvtxx = 0xa2
181−mulx0 = 0xa3
182−divx0 = 0xa4
183−cvtxx0 = 0xa5
184−mulx1 = 0xa6
185−divx1 = 0xa7
186−cvtxx1 = 0xa8
187−cvtfx = 0xa9
188−cvtxf = 0xaa
189−expw = 0xab
190−expl = 0xac
191−expf = 0xad
192−self = 0xae
193−
194−names = [
18+from utils import read_B, read_OP
19+
20+# Define string representations of the opcodes.
21+
22+instruction_names = [
19523 "nop", "alt", "nbalt", "goto", "call", "frame", "spawn", "runt",
19624 "load", "mcall", "mspawn", "mframe", "ret", "jmp", "case", "exit",
19725 "new", "newa", "newcb", "newcw", "newcf", "newcp", "newcm", "newcmp",
@@ -215,3 +43,806 @@ names = [ · 17 unmodified lines
21543 "mulx", "divx", "cvtxx", "mulx0", "divx0", "cvtxx0", "mulx1", "divx1",
21644 "cvtxx1", "cvtfx", "cvtxf", "expw", "expl", "expf", "self"
21745 ]
46+
47+
48+class Instruction:
49+
50+ def read(self, f):
51+
52+ self.opcode = read_B(f)
53+ self.address_mode = read_B(f)
54+
55+ middle = self.address_mode & 0xc0
56+ self.middle, self.middle_type = self.read_middle_operand(middle, f)
57+
58+ source = (self.address_mode & 0x38) >> 3
59+ self.source, self.source_type = self.read_operand(source, f)
60+
61+ destination = self.address_mode & 0x07
62+ self.destination, self.destination_type = self.read_operand(destination, f)
63+
64+ return self
65+
66+ def read_operand(self, operand, f):
67+
68+ # Since we shift the address flags for the source operand, we can
69+ # check both source and destination operands using the same values.
70+
71+ if operand == 0x00:
72+ operand = read_OP(f)
73+ operand_type = "LO(MP)"
74+ elif operand == 0x01:
75+ operand = read_OP(f)
76+ operand_type = "LO(FP)"
77+ elif operand == 0x02:
78+ operand = read_OP(f)
79+ operand_type = "$OP"
80+
81+ # No operand for 0x03.
82+
83+ elif operand == 0x04:
84+ operand = (read_OP(f), read_OP(f))
85+ operand_type = "SO(SO(MP))"
86+ elif operand == 0x05:
87+ operand = (read_OP(f), read_OP(f))
88+ operand_type = "SO(SO(FP))"
89+ else:
90+ operand = None
91+ operand_type = None
92+
93+ return operand, operand_type
94+
95+ def read_middle_operand(self, operand, f):
96+
97+ # The middle operand bits are not shifted.
98+
99+ if operand == 0x40:
100+ operand = read_OP(f)
101+ operand_type = "$SI"
102+ elif operand == 0x80:
103+ operand = read_OP(f)
104+ operand_type = "SO(FP)"
105+ elif operand == 0xc0:
106+ operand = read_OP(f)
107+ operand_type = "SO(MP)"
108+ else:
109+ operand = None
110+ operand_type = None
111+
112+ return operand, operand_type
113+
114+ def __repr__(self):
115+
116+ try:
117+ name = instruction_names[self.opcode]
118+ except IndexError:
119+ name = hex(self.opcode)
120+
121+ operands = []
122+ comments = []
123+
124+ for op, optype in (self.source, self.source_type), \
125+ (self.middle, self.middle_type), \
126+ (self.destination, self.destination_type):
127+
128+ if optype == "$SI":
129+ operands.append("$%x" % op)
130+ elif optype == "SO(FP)":
131+ operands.append("%i(fp)" % op)
132+ elif optype == "SO(MP)":
133+ operands.append("%i(mp)" % op)
134+ elif optype == "LO(MP)":
135+ operands.append("%i(mp)" % op)
136+ elif optype == "LO(FP)":
137+ operands.append("%i(fp)" % op)
138+ elif optype == "$OP":
139+ operands.append("$%x" % op)
140+ elif optype == "SO(SO(MP))":
141+ operands.append("%i(%i(mp))" % op)
142+ elif optype == "SO(SO(FP))":
143+ operands.append("%i(%i(fp))" % op)
144+
145+ return name + " " + ", ".join(operands)
146+
147+
148+# Define the instructions and their opcode values.
149+
150+class nop(Instruction):
151+
152+ opcode = 0x00
153+
154+class alt(Instruction):
155+
156+ opcode = 0x01
157+
158+class nbalt(Instruction):
159+
160+ opcode = 0x02
161+
162+class goto(Instruction):
163+
164+ opcode = 0x03
165+
166+class call(Instruction):
167+
168+ opcode = 0x04
169+
170+class frame(Instruction):
171+
172+ opcode = 0x05
173+
174+class spawn(Instruction):
175+
176+ opcode = 0x06
177+
178+class runt(Instruction):
179+
180+ opcode = 0x07
181+
182+class load(Instruction):
183+
184+ opcode = 0x08
185+
186+class mcall(Instruction):
187+
188+ opcode = 0x09
189+
190+class mspawn(Instruction):
191+
192+ opcode = 0x0a
193+
194+class mframe(Instruction):
195+
196+ opcode = 0x0b
197+
198+class ret(Instruction):
199+
200+ opcode = 0x0c
201+
202+class jmp(Instruction):
203+
204+ opcode = 0x0d
205+
206+class case(Instruction):
207+
208+ opcode = 0x0e
209+
210+class exit(Instruction):
211+
212+ opcode = 0x0f
213+
214+class new(Instruction):
215+
216+ opcode = 0x10
217+
218+class newa(Instruction):
219+
220+ opcode = 0x11
221+
222+class newcb(Instruction):
223+
224+ opcode = 0x12
225+
226+class newcw(Instruction):
227+
228+ opcode = 0x13
229+
230+class newcf(Instruction):
231+
232+ opcode = 0x14
233+
234+class newcp(Instruction):
235+
236+ opcode = 0x15
237+
238+class newcm(Instruction):
239+
240+ opcode = 0x16
241+
242+class newcmp(Instruction):
243+
244+ opcode = 0x17
245+
246+class send(Instruction):
247+
248+ opcode = 0x18
249+
250+class recv(Instruction):
251+
252+ opcode = 0x19
253+
254+class consb(Instruction):
255+
256+ opcode = 0x1a
257+
258+class consw(Instruction):
259+
260+ opcode = 0x1b
261+
262+class consp(Instruction):
263+
264+ opcode = 0x1c
265+
266+class consf(Instruction):
267+
268+ opcode = 0x1d
269+
270+class consm(Instruction):
271+
272+ opcode = 0x1e
273+
274+class consmp(Instruction):
275+
276+ opcode = 0x1f
277+
278+class headb(Instruction):
279+
280+ opcode = 0x20
281+
282+class headw(Instruction):
283+
284+ opcode = 0x21
285+
286+class headp(Instruction):
287+
288+ opcode = 0x22
289+
290+class headf(Instruction):
291+
292+ opcode = 0x23
293+
294+class headm(Instruction):
295+
296+ opcode = 0x24
297+
298+class headmp(Instruction):
299+
300+ opcode = 0x25
301+
302+class tail(Instruction):
303+
304+ opcode = 0x26
305+
306+class lea(Instruction):
307+
308+ opcode = 0x27
309+
310+class indx(Instruction):
311+
312+ opcode = 0x28
313+
314+class movp(Instruction):
315+
316+ opcode = 0x29
317+
318+class movm(Instruction):
319+
320+ opcode = 0x2a
321+
322+class movmp(Instruction):
323+
324+ opcode = 0x2b
325+
326+class movb(Instruction):
327+
328+ opcode = 0x2c
329+
330+class movw(Instruction):
331+
332+ opcode = 0x2d
333+
334+class movf(Instruction):
335+
336+ opcode = 0x2e
337+
338+class cvtbw(Instruction):
339+
340+ opcode = 0x2f
341+
342+class cvtwb(Instruction):
343+
344+ opcode = 0x30
345+
346+class cvtfw(Instruction):
347+
348+ opcode = 0x31
349+
350+class cvtwf(Instruction):
351+
352+ opcode = 0x32
353+
354+class cvtca(Instruction):
355+
356+ opcode = 0x33
357+
358+class cvtac(Instruction):
359+
360+ opcode = 0x34
361+
362+class cvtwc(Instruction):
363+
364+ opcode = 0x35
365+
366+class cvtcw(Instruction):
367+
368+ opcode = 0x36
369+
370+class cvtfc(Instruction):
371+
372+ opcode = 0x37
373+
374+class cvtcf(Instruction):
375+
376+ opcode = 0x38
377+
378+class addb(Instruction):
379+
380+ opcode = 0x39
381+
382+class addw(Instruction):
383+
384+ opcode = 0x3a
385+
386+class addf(Instruction):
387+
388+ opcode = 0x3b
389+
390+class subb(Instruction):
391+
392+ opcode = 0x3c
393+
394+class subw(Instruction):
395+
396+ opcode = 0x3d
397+
398+class subf(Instruction):
399+
400+ opcode = 0x3e
401+
402+class mulb(Instruction):
403+
404+ opcode = 0x3f
405+
406+class mulw(Instruction):
407+
408+ opcode = 0x40
409+
410+class mulf(Instruction):
411+
412+ opcode = 0x41
413+
414+class divb(Instruction):
415+
416+ opcode = 0x42
417+
418+class divw(Instruction):
419+
420+ opcode = 0x43
421+
422+class divf(Instruction):
423+
424+ opcode = 0x44
425+
426+class modw(Instruction):
427+
428+ opcode = 0x45
429+
430+class modb(Instruction):
431+
432+ opcode = 0x46
433+
434+class andb(Instruction):
435+
436+ opcode = 0x47
437+
438+class andw(Instruction):
439+
440+ opcode = 0x48
441+
442+class orb(Instruction):
443+
444+ opcode = 0x49
445+
446+class orw(Instruction):
447+
448+ opcode = 0x4a
449+
450+class xorb(Instruction):
451+
452+ opcode = 0x4b
453+
454+class xorw(Instruction):
455+
456+ opcode = 0x4c
457+
458+class shlb(Instruction):
459+
460+ opcode = 0x4d
461+
462+class shlw(Instruction):
463+
464+ opcode = 0x4e
465+
466+class shrb(Instruction):
467+
468+ opcode = 0x4f
469+
470+class shrw(Instruction):
471+
472+ opcode = 0x50
473+
474+class insc(Instruction):
475+
476+ opcode = 0x51
477+
478+class indc(Instruction):
479+
480+ opcode = 0x52
481+
482+class addc(Instruction):
483+
484+ opcode = 0x53
485+
486+class lenc(Instruction):
487+
488+ opcode = 0x54
489+
490+class lena(Instruction):
491+
492+ opcode = 0x55
493+
494+class lenl(Instruction):
495+
496+ opcode = 0x56
497+
498+class beqb(Instruction):
499+
500+ opcode = 0x57
501+
502+class bneb(Instruction):
503+
504+ opcode = 0x58
505+
506+class bltb(Instruction):
507+
508+ opcode = 0x59
509+
510+class bleb(Instruction):
511+
512+ opcode = 0x5a
513+
514+class bgtb(Instruction):
515+
516+ opcode = 0x5b
517+
518+class bgeb(Instruction):
519+
520+ opcode = 0x5c
521+
522+class beqw(Instruction):
523+
524+ opcode = 0x5d
525+
526+class bnew(Instruction):
527+
528+ opcode = 0x5e
529+
530+class bltw(Instruction):
531+
532+ opcode = 0x5f
533+
534+class blew(Instruction):
535+
536+ opcode = 0x60
537+
538+class bgtw(Instruction):
539+
540+ opcode = 0x61
541+
542+class bgew(Instruction):
543+
544+ opcode = 0x62
545+
546+class beqf(Instruction):
547+
548+ opcode = 0x63
549+
550+class bnef(Instruction):
551+
552+ opcode = 0x64
553+
554+class bltf(Instruction):
555+
556+ opcode = 0x65
557+
558+class blef(Instruction):
559+
560+ opcode = 0x66
561+
562+class bgtf(Instruction):
563+
564+ opcode = 0x67
565+
566+class bgef(Instruction):
567+
568+ opcode = 0x68
569+
570+class beqc(Instruction):
571+
572+ opcode = 0x69
573+
574+class bnec(Instruction):
575+
576+ opcode = 0x6a
577+
578+class bltc(Instruction):
579+
580+ opcode = 0x6b
581+
582+class blec(Instruction):
583+
584+ opcode = 0x6c
585+
586+class bgtc(Instruction):
587+
588+ opcode = 0x6d
589+
590+class bgec(Instruction):
591+
592+ opcode = 0x6e
593+
594+class slicea(Instruction):
595+
596+ opcode = 0x6f
597+
598+class slicela(Instruction):
599+
600+ opcod = 0x70
601+
602+class slicec(Instruction):
603+
604+ opcode = 0x71
605+
606+class indw(Instruction):
607+
608+ opcode = 0x72
609+
610+class indf(Instruction):
611+
612+ opcode = 0x73
613+
614+class indb(Instruction):
615+
616+ opcode = 0x74
617+
618+class negf(Instruction):
619+
620+ opcode = 0x75
621+
622+class movl(Instruction):
623+
624+ opcode = 0x76
625+
626+class addl(Instruction):
627+
628+ opcode = 0x77
629+
630+class subl(Instruction):
631+
632+ opcode = 0x78
633+
634+class divl(Instruction):
635+
636+ opcode = 0x79
637+
638+class modl(Instruction):
639+
640+ opcode = 0x7a
641+
642+class mull(Instruction):
643+
644+ opcode = 0x7b
645+
646+class andl(Instruction):
647+
648+ opcode = 0x7c
649+
650+class orl(Instruction):
651+
652+ opcode = 0x7d
653+
654+class xorl(Instruction):
655+
656+ opcode = 0x7e
657+
658+class shll(Instruction):
659+
660+ opcode = 0x7f
661+
662+class shrl(Instruction):
663+
664+ opcode = 0x80
665+
666+class bnel(Instruction):
667+
668+ opcode = 0x81
669+
670+class bltl(Instruction):
671+
672+ opcode = 0x82
673+
674+class blel(Instruction):
675+
676+ opcode = 0x83
677+
678+class bgtl(Instruction):
679+
680+ opcode = 0x84
681+
682+class bgel(Instruction):
683+
684+ opcode = 0x85
685+
686+class beql(Instruction):
687+
688+ opcode = 0x86
689+
690+class cvtlf(Instruction):
691+
692+ opcode = 0x87
693+
694+class cvtfl(Instruction):
695+
696+ opcode = 0x88
697+
698+class cvtlw(Instruction):
699+
700+ opcode = 0x89
701+
702+class cvtwl(Instruction):
703+
704+ opcode = 0x8a
705+
706+class cvtlc(Instruction):
707+
708+ opcode = 0x8b
709+
710+class cvtcl(Instruction):
711+
712+ opcode = 0x8c
713+
714+class headl(Instruction):
715+
716+ opcode = 0x8d
717+
718+class consl(Instruction):
719+
720+ opcode = 0x8e
721+
722+class newcl(Instruction):
723+
724+ opcode = 0x8f
725+
726+class casec(Instruction):
727+
728+ opcode = 0x90
729+
730+class indl(Instruction):
731+
732+ opcode = 0x91
733+
734+class movpc(Instruction):
735+
736+ opcode = 0x92
737+
738+class tcmp(Instruction):
739+
740+ opcode = 0x93
741+
742+class mnewz(Instruction):
743+
744+ opcode = 0x94
745+
746+class cvtrf(Instruction):
747+
748+ opcode = 0x95
749+
750+class cvtfr(Instruction):
751+
752+ opcode = 0x96
753+
754+class cvtws(Instruction):
755+
756+ opcode = 0x97
757+
758+class cvtsw(Instruction):
759+
760+ opcode = 0x98
761+
762+class lsrw(Instruction):
763+
764+ opcode = 0x99
765+
766+class lsrl(Instruction):
767+
768+ opcode = 0x9a
769+
770+class eclr(Instruction):
771+
772+ opcode = 0x9b
773+
774+class newz(Instruction):
775+
776+ opcode = 0x9c
777+
778+class newaz(Instruction):
779+
780+ opcode = 0x9d
781+
782+class raise_(Instruction):
783+
784+ opcode = 0x9e
785+
786+class casel(Instruction):
787+
788+ opcode = 0x9f
789+
790+class mulx(Instruction):
791+
792+ opcode = 0xa0
793+
794+class divx(Instruction):
795+
796+ opcode = 0xa1
797+
798+class cvtxx(Instruction):
799+
800+ opcode = 0xa2
801+
802+class mulx0(Instruction):
803+
804+ opcode = 0xa3
805+
806+class divx0(Instruction):
807+
808+ opcode = 0xa4
809+
810+class cvtxx0(Instruction):
811+
812+ opcode = 0xa5
813+
814+class mulx1(Instruction):
815+
816+ opcode = 0xa6
817+
818+class divx1(Instruction):
819+
820+ opcode = 0xa7
821+
822+class cvtxx1(Instruction):
823+
824+ opcode = 0xa8
825+
826+class cvtfx(Instruction):
827+
828+ opcode = 0xa9
829+
830+class cvtxf(Instruction):
831+
832+ opcode = 0xaa
833+
834+class expw(Instruction):
835+
836+ opcode = 0xab
837+
838+class expl(Instruction):
839+
840+ opcode = 0xac
841+
842+class expf(Instruction):
843+
844+ opcode = 0xad
845+
846+class self(Instruction):
847+
848+ opcode = 0xae
utils.py+98−0
@@ -0,0 +1,98 @@
1+"""
2+Copyright (C) 2017 David Boddie <david@boddie.org.uk>
3+
4+This program is free software: you can redistribute it and/or modify
5+it under the terms of the GNU General Public License as published by
6+the Free Software Foundation, either version 3 of the License, or
7+(at your option) any later version.
8+
9+This program is distributed in the hope that it will be useful,
10+but WITHOUT ANY WARRANTY; without even the implied warranty of
11+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+GNU General Public License for more details.
13+
14+You should have received a copy of the GNU General Public License
15+along with this program. If not, see <http://www.gnu.org/licenses/>.
16+"""
17+
18+from struct import calcsize, pack, unpack
19+
20+def _read(f, format):
21+
22+ size = calcsize(format)
23+ return unpack(format, f.read(size))[0]
24+
25+def read_B(f):
26+ # byte, 8-bit unsigned
27+ return unpack(">B", f.read(1))[0]
28+
29+def read_OP(f):
30+
31+ s = f.read(1)
32+ v = unpack(">B", s)[0]
33+
34+ encoding = v & 0xc0
35+
36+ if encoding == 0x80:
37+ s += f.read(1)
38+ v = unpack(">H", s)[0] & 0x3fff
39+ if v >= 0x2000:
40+ v = v - 0x4000
41+
42+ elif encoding == 0xc0:
43+ s += f.read(3)
44+ v = unpack(">I", s)[0] & 0x3fffffff
45+ if v >= 0x20000000:
46+ v = v - 0x40000000
47+ else:
48+ # The top bit is clear, the next-to-top bit can be 0 or 1.
49+ # -64 (0xc0) <= original value <= 63 (0x2f)
50+ # -64 (0x40) <= encoded value <= 63 (0x2f)
51+ if encoding != 0:
52+ # The next-to-top bit is set meaning that
53+ # -64 <= original value <= -1
54+ v = v - 0x80
55+
56+ return v
57+
58+def read_W(f):
59+ # 32-bit word
60+ return unpack(">i", f.read(4))[0]
61+
62+def read_F(f):
63+ # 64-bit float
64+ return unpack(">d", f.read(8))[0]
65+
66+def read_L(f):
67+ # 64-bit big integer
68+ # Signed or unsigned? Assume signed for now.
69+ return unpack(">q", f.read(8))[0]
70+
71+def read_P(f):
72+ # 32-bit pointer
73+ return unpack(">I", f.read(4))[0]
74+
75+def read_C(f):
76+ # UTF-8 encoded string
77+ s = ""
78+ while True:
79+ c = f.read(1)
80+ if c == "\x00":
81+ break
82+ s += c
83+
84+ return s
85+
86+# Currently unused:
87+
88+def read_SO(f):
89+
90+ return unpack(">H", f.read(2))[0]
91+
92+def read_SI(f):
93+
94+ return unpack(">h", f.read(2))[0]
95+
96+def read_LO(f):
97+
98+ return unpack(">i", f.read(4))[0]