5178aa63607151e5926a29af81a88bb12f701443
[platform/upstream/nasm.git] / insns.bas
1 ' INFO_1: Converter for INSNS.DAT to INSNSA.C and INSNSD.C
2 '
3 ' INFO_2: Written by Mark Junker in 1997
4 '         InterNet: mjs@prg.hannover.sgh-net.de
5 '         FIDO:     Mark Junker@2:2437/47.21
6 '
7 ' COMMENT: While I wrote this program I often asked me, if it isn't easier
8 '          to write an interpreter for Perl-scripts :]
9 '
10 ' COMMENT: To start the program press SHIFT+F5 within the QBasic IDE
11 '          or start it from the command-line with QBASIC /RUN MACROS
12 '
13 '
14 ' THIS PROGRAM NEEDS TO BE UPDATED -- it doesn't create insnsi.h
15 ' and insnsn.c.  However, Perl interpreters are now available for both
16 ' DOS and Windows, so it seems pointless to spend the effort.
17 '
18
19 DEFINT A-Z
20
21 DECLARE FUNCTION ReplaceOp$ (a$)
22 DECLARE FUNCTION StrTrimLeft$ (a$, b$)
23 DECLARE FUNCTION StrTrimRight$ (a$, b$)
24 DECLARE FUNCTION StrTrim$ (a$, b$)
25 DECLARE SUB StrSplitString (SplitString$, SplitChars$, SplitField$(), SplitCount%)
26 DECLARE FUNCTION Min% (a%, b%)
27 DECLARE FUNCTION StrInstrLeft% (SearchStart%, SearchIn$, SearchFor$)
28 DECLARE FUNCTION StrAscii% (a$)
29
30
31 CONST MaxOpCodeBase = 3
32 CONST MaxOpCodeType = 8
33
34 CLS
35 DIM LineData$(1 TO 2)
36 DIM StrucData$(1 TO 5)
37 DIM OpCodeList$(0 TO 255)
38 DIM OpCodeByte(1 TO MaxOpCodeType, 1 TO MaxOpCodeBase)
39 DIM OpCodeStat(1 TO 10)   ' don't need mode :)
40
41 Instructs$ = ""
42 LineOfs$ = ""
43
44 OPEN "I", 1, "insns.dat"
45 OPEN "B", 3, "insns.tmp"
46
47 qt$ = CHR$(34)
48 crlf$ = CHR$(13) + CHR$(10)
49
50
51 '
52 ' preprocessing the current file
53 '
54
55 HexChar$ = "0123456789ABCDEF"
56
57 PRINT "Preprocessing INSNS.DAT"
58 OpCodes = 0
59 OpCodeDebug = 0
60 NowLineOfs& = 1
61 lineNr = 0
62 WHILE NOT EOF(1)
63   lineNr = lineNr + 1
64   IF (lineNr AND 15) = 0 THEN
65     LOCATE , 1
66     PRINT lineNr, OpCodes, OpCodeDebug;
67   END IF
68
69   LINE INPUT #1, l$
70   CALL StrSplitString(l$, ";", LineData$(), SplitCount)
71   IF SplitCount THEN
72     LineData$(1) = StrTrim$(LineData$(1), CHR$(9) + " ")
73     IF LEN(LineData$(1)) THEN
74       CALL StrSplitString(LineData$(1), " ", StrucData$(), cntSplit)
75       IF cntSplit <> 4 THEN
76         PRINT "line"; lineNr; " does not contain four fields"
77         END
78       END IF
79
80       tst$ = UCASE$(StrucData$(2))
81       res$ = ""
82       cnt% = 1
83       isfirst = 1
84       op = 1
85       p = StrInstrLeft(1, tst$ + ",", "|:,")
86       WHILE p
87         h$ = ReplaceOp$(MID$(tst$, op, p - op))
88         IF LEN(h$) THEN
89           SELECT CASE MID$(tst$, p, 1)
90           CASE ""
91             IF isfirst THEN
92               res$ = res$ + h$
93             ELSE
94               res$ = res$ + "|" + h$
95             END IF
96             isfirst = 0
97           CASE ","
98             IF isfirst THEN
99               res$ = res$ + h$ + ","
100             ELSE
101               res$ = res$ + "|" + h$ + ","
102             END IF
103             cnt% = cnt% + 1
104             isfirst = 1
105           CASE "|"
106             IF isfirst THEN
107               res$ = res$ + h$
108             ELSE
109               res$ = res$ + "|" + h$
110             END IF
111             isfirst = 0
112           CASE ":"
113             res$ = res$ + h$ + "|COLON,"
114             cnt% = cnt% + 1
115           END SELECT
116         END IF
117         op = p + 1
118         p = StrInstrLeft(op, tst$ + ",", "|:,")
119       WEND
120       FOR a = cnt% + 1 TO 3
121         res$ = res$ + ",0"
122       NEXT
123       StrucData$(2) = res$
124       IF LEFT$(res$, 2) = "0," THEN cnt% = cnt% - 1
125       StrucData$(5) = LTRIM$(STR$(cnt%))
126
127       NoDebug = 0
128       res$ = ""
129       tst$ = UCASE$(StrucData$(4))
130       op = 1
131       p = INSTR(tst$ + ",", ",")
132       isfirst = 1
133       WHILE p
134         h$ = MID$(tst$, op, p - op)
135         IF h$ = "ND" THEN
136           NoDebug = 1
137         ELSE
138           IF isfirst THEN
139             res$ = res$ + "IF_" + h$
140           ELSE
141             res$ = res$ + "|IF_" + h$
142           END IF
143           isfirst = 0
144         END IF
145         op = p + 1
146         p = INSTR(op, tst$ + ",", ",")
147       WEND
148       StrucData$(4) = res$
149
150       tst$ = UCASE$(StrucData$(3))
151       SELECT CASE tst$
152       CASE "IGNORE"
153         GOTO skipOpCode
154       CASE "\0", "\340"
155         OpCodeDebug = OpCodeDebug + 1    ' don't forget to increment
156         GOTO skipOpCode
157       END SELECT
158
159       AddRegs = 0
160       AddCCode = 0
161       NextIsOpCode = 0
162       opCodeVal$ = ""
163       op = 1
164       p = INSTR(tst$ + "\", "\")
165       DO WHILE p
166         h$ = MID$(tst$, op, p - op)
167         IF LEFT$(h$, 1) = "X" THEN
168           opCodeVal$ = CHR$(VAL("&H" + MID$(h$, 2)))
169           EXIT DO
170         ELSE
171           SELECT CASE h$
172           CASE "1", "2", "3"
173             NextIsOpCode = 1
174           CASE "4"
175             opCodeVal$ = CHR$(&H7) + CHR$(&H17) + CHR$(&H1F)
176             EXIT DO
177           CASE "5"
178             opCodeVal$ = CHR$(&HA1) + CHR$(&HA9)
179             EXIT DO
180           CASE "6"
181             opCodeVal$ = CHR$(&H6) + CHR$(&HE) + CHR$(&H16) + CHR$(&H1E)
182             EXIT DO
183           CASE "7"
184             opCodeVal$ = CHR$(&HA0) + CHR$(&HA8)
185             EXIT DO
186           CASE "10", "11", "12"
187             NextIsOpCode = 1
188             AddRegs = VAL(h$) - 9
189           CASE "330"
190             NextIsOpCode = 1
191             AddCCode = VAL(h$) - 329
192           CASE "17"
193             opCodeVal$ = CHR$(0)
194             EXIT DO
195           CASE ELSE
196             IF NextIsOpCode THEN
197               PRINT "Line:"; lineNr
198               PRINT "Unknown value: " + h$
199               END
200             END IF
201           END SELECT
202         END IF
203         op = p + 1
204         p = INSTR(op, tst$ + "\", "\")
205       LOOP
206       IF (p = 0) THEN
207         PRINT "No opcode found in line"; lineNr
208         PRINT "Line:"
209         PRINT l$
210         END
211       END IF
212
213       IF NoDebug = 0 THEN
214         FOR a = 1 TO LEN(opCodeVal$)
215           h = ASC(MID$(opCodeVal$, a, 1))
216           OpCodeStr$ = MKI$(OpCodeDebug)
217           IF AddRegs THEN
218             EndNr = 7
219           ELSEIF AddCCode THEN
220             EndNr = 15
221           ELSE
222             EndNr = 0
223           END IF
224           FOR b = 0 TO EndNr
225             OpCodeList$(h + b) = OpCodeList$(h + b) + OpCodeStr$
226           NEXT
227         NEXT
228         OpCodeDebug = OpCodeDebug + 1
229       END IF
230
231 skipOpCode:
232       OpCodes = OpCodes + 1
233       LineOfs$ = LineOfs$ + MKL$(NowLineOfs&)
234       LineLg = 1
235       h$ = CHR$(NoDebug)
236       PUT #3, NowLineOfs&, h$
237       NowLineOfs& = NowLineOfs& + 1
238       FOR a = 1 TO 5
239         lg = LEN(StrucData$(a))
240         h$ = CHR$(lg) + StrucData$(a)
241         PUT #3, NowLineOfs&, h$
242         NowLineOfs& = NowLineOfs& + lg + 1
243         LineLg = LineLg + lg + 1
244       NEXT
245       LineOfs$ = LineOfs$ + MKI$(LineLg)
246     END IF
247   END IF
248 WEND
249 LOCATE , 1
250 PRINT lineNr, OpCodes, OpCodeDebug
251
252
253 '
254 ' creating insnsa.c
255 '
256
257
258 PRINT "Creating INSNSA.C"
259
260 OPEN "O", 2, "insnsa.c"
261 strBegStart$ = "static struct itemplate instrux_"
262 strBegEnd$ = "[] = {"
263 strEnd$ = "    {-1}" + crlf$ + "};" + crlf$
264
265 PRINT #2, "/* This file auto-generated from insns.dat by insns.bas - don't edit it */"
266 PRINT #2, ""
267 PRINT #2, "#include <stdio.h>"
268 PRINT #2, "#include " + qt$ + "nasm.h" + qt$
269 PRINT #2, "#include " + qt$ + "insns.h" + qt$
270 PRINT #2, ""
271
272 oldOpCode$ = ""
273 pOfs = 1
274 FOR a = 1 TO OpCodes
275   LineOfs& = CVL(MID$(LineOfs$, pOfs, 4))
276   l$ = SPACE$(CVI(MID$(LineOfs$, pOfs + 4, 2)))
277   pOfs = pOfs + 6
278   GET #3, LineOfs&, l$
279
280   ' split data into fields
281   NoDebug = ASC(LEFT$(l$, 1))
282   pLn = 2
283   FOR b = 1 TO 5
284     lgLn = ASC(MID$(l$, pLn, 1))
285     StrucData$(b) = MID$(l$, pLn + 1, lgLn)
286     pLn = pLn + lgLn + 1
287   NEXT
288
289   IF oldOpCode$ <> StrucData$(1) THEN
290     Instructs$ = Instructs$ + StrucData$(1) + CHR$(0)
291     IF LEN(oldOpCode$) THEN PRINT #2, strEnd$
292     PRINT #2, strBegStart$ + StrucData$(1) + strBegEnd$
293     oldOpCode$ = StrucData$(1)
294   END IF
295   SELECT CASE UCASE$(StrucData$(3))
296   CASE "IGNORE"
297   CASE ELSE
298     PRINT #2, "    {I_" + oldOpCode$ + ", " + StrucData$(5) + ", {" + StrucData$(2) + "}, " + qt$ + StrucData$(3) + qt$ + ", " + StrucData$(4) + "},"
299   END SELECT
300 NEXT
301 IF LEN(oldOpCode$) THEN PRINT #2, strEnd$
302
303 PRINT #2, "struct itemplate *nasm_instructions[] = {"
304 op = 1
305 p = INSTR(Instructs$, CHR$(0))
306 WHILE p
307   h$ = MID$(Instructs$, op, p - op)
308   PRINT #2, "    instrux_" + h$ + ","
309   op = p + 1
310   p = INSTR(op, Instructs$, CHR$(0))
311 WEND
312 PRINT #2, "};"
313
314 CLOSE 2
315
316
317
318 '
319 ' creating insnsd.c
320 '
321
322
323 PRINT "Creating INSNSD.C"
324
325 OPEN "O", 2, "insnsd.c"
326
327 PRINT #2, "/* This file auto-generated from insns.dat by insns.bas - don't edit it */"
328 PRINT #2, ""
329 PRINT #2, "#include <stdio.h>"
330 PRINT #2, "#include " + qt$ + "nasm.h" + qt$
331 PRINT #2, "#include " + qt$ + "insns.h" + qt$
332 PRINT #2, ""
333
334
335 PRINT #2, "static struct itemplate instrux[] = {"
336 pOfs = 1
337 FOR a = 1 TO OpCodes
338   LineOfs& = CVL(MID$(LineOfs$, pOfs, 4))
339   l$ = SPACE$(CVI(MID$(LineOfs$, pOfs + 4, 2)))
340   pOfs = pOfs + 6
341   GET #3, LineOfs&, l$
342
343   ' split data into fields
344   NoDebug = ASC(LEFT$(l$, 1))
345   pLn = 2
346   FOR b = 1 TO 5
347     lgLn = ASC(MID$(l$, pLn, 1))
348     StrucData$(b) = MID$(l$, pLn + 1, lgLn)
349     pLn = pLn + lgLn + 1
350   NEXT
351
352   IF NoDebug OR (UCASE$(StrucData$(3)) = "IGNORE") THEN
353     ' ignorieren
354   ELSE
355     PRINT #2, "    {I_" + StrucData$(1) + ", " + StrucData$(5) + ", {" + StrucData$(2) + "}, " + qt$ + StrucData$(3) + qt$ + ", " + StrucData$(4) + "},"
356   END IF
357 NEXT
358 PRINT #2, "    {-1}" + crlf$ + "};" + crlf$
359
360
361 OpCodeBegS$ = "static struct itemplate *itable_"
362 OpCodeBegE$ = "[] = {"
363 OpCodeEnd$ = "    NULL" + crlf$ + "};" + crlf$
364
365 FOR a = 0 TO 255
366   PRINT #2, OpCodeBegS$ + RIGHT$("00" + HEX$(a), 2) + OpCodeBegE$
367   h$ = OpCodeList$(a)
368   FOR b = 1 TO LEN(h$) STEP 2
369     OpCodePos = CVI(MID$(h$, b, 2))
370     PRINT #2, "    instrux +" + STR$(OpCodePos) + ","
371   NEXT
372   PRINT #2, OpCodeEnd$
373 NEXT
374
375 PRINT #2, "struct itemplate **itable[] = {"
376 FOR a = 0 TO 255
377   PRINT #2, "    itable_" + RIGHT$("00" + HEX$(a), 2) + ","
378 NEXT
379 PRINT #2, "};"
380
381 CLOSE 2
382
383
384
385 CLOSE 3
386 KILL "insns.tmp"
387 CLOSE 1
388 SYSTEM
389
390 FUNCTION ReplaceOp$ (a$)
391   tst$ = UCASE$(a$)
392   SELECT CASE tst$
393 '  CASE "ND"
394 '    ReplaceOp$ = ""
395   CASE "VOID", ""
396     ReplaceOp$ = "0"
397   CASE "IMM"
398     ReplaceOp$ = "IMMEDIATE"
399   CASE "MEM"
400     ReplaceOp$ = "MEMORY"
401   CASE "MEM8", "MEM16", "MEM32", "MEM64", "MEM80"
402     ReplaceOp$ = "MEMORY|BITS" + MID$(tst$, 4)
403   CASE "REG8", "REG16", "REG32"
404     ReplaceOp$ = tst$
405   CASE "RM8", "RM16", "RM32"
406     ReplaceOp$ = "REGMEM|BITS" + MID$(tst$, 3)
407   CASE "IMM8", "IMM16", "IMM32"
408     ReplaceOp$ = "IMMEDIATE|BITS" + MID$(tst$, 4)
409   CASE ELSE
410     ReplaceOp$ = tst$
411   END SELECT
412 END FUNCTION
413
414 FUNCTION Min% (a%, b%)
415   IF a% < b% THEN Min% = a% ELSE Min% = b%
416 END FUNCTION
417
418 FUNCTION StrAscii (a$)
419   IF LEN(a$) = 0 THEN
420     StrAscii = -1
421   ELSE
422     StrAscii = ASC(a$)
423   END IF
424 END FUNCTION
425
426 ' same as =INSTR(SearchStart, SearchIn, ANY SearchFor$) in PowerBASIC(tm)
427 '
428 FUNCTION StrInstrLeft (SearchStart, SearchIn$, SearchFor$)
429  ValuesCount = LEN(SearchFor$)
430  MaxValue = LEN(SearchIn$) + 1
431  MinValue = MaxValue
432  FOR Counter1 = 1 TO ValuesCount
433   SearchChar$ = MID$(SearchFor$, Counter1, 1)
434   hVal2 = INSTR(SearchStart, SearchIn$, SearchChar$)
435   IF hVal2 > 0 THEN MinValue = Min%(hVal2, MinValue)
436  NEXT
437  IF MinValue = MaxValue THEN MinValue = 0
438  StrInstrLeft = MinValue
439 END FUNCTION
440
441 '
442 ' This is a very damn fuckin' shit version of this splitting routine.
443 ' At this time, it's not very useful :]
444 '
445 SUB StrSplitString (SplitString$, SplitChars$, SplitField$(), SplitCount)
446   StartIndex = LBOUND(SplitField$)
447   LastIndex = UBOUND(SplitField$)
448   ActualIndex& = StartIndex
449   SplitCount = 0
450
451   LastPos = 1
452   FoundPos = StrInstrLeft(LastPos, SplitString$, SplitChars$ + CHR$(34))
453   GetDirect = 0
454   EndLoop = 0
455   TempString$ = ""
456   DO WHILE FoundPos > 0
457     FoundCharVal = StrAscii(MID$(SplitString$, FoundPos, 1))
458     PosDiff = (FoundPos - LastPos) + 1
459     SELECT CASE FoundCharVal
460     CASE 34
461       TempString$ = TempString$ + MID$(SplitString$, LastPos, PosDiff - 1)
462       SELECT CASE EndLoop
463       CASE 0
464         EndLoop = 2
465       CASE 3
466         EndLoop = 0
467       END SELECT
468     CASE ELSE
469       TempString$ = TempString$ + MID$(SplitString$, LastPos, PosDiff - 1)
470       SplitField$(ActualIndex&) = TempString$
471       TempString$ = ""
472       ActualIndex& = ActualIndex& + 1
473       IF ActualIndex& > LastIndex THEN
474         ActualIndex& = LastIndex
475         EndLoop = 1
476       END IF
477     END SELECT
478     SELECT CASE EndLoop
479     CASE 0
480       DO
481         LastPos = FoundPos + 1
482         FoundPos = StrInstrLeft(LastPos, SplitString$, SplitChars$)
483       LOOP WHILE LastPos = FoundPos
484       FoundPos = StrInstrLeft(LastPos, SplitString$, SplitChars$ + CHR$(34))
485     CASE 1
486       FoundPos = 0
487       LastPos = LEN(SplitString$) + 1
488     CASE 2
489       EndLoop = 3
490       LastPos = FoundPos + 1
491       FoundPos = StrInstrLeft(LastPos, SplitString$, CHR$(34))
492       IF FoundPos = 0 THEN
493        SplitString$ = SplitString$ + CHR$(34)
494        FoundPos = LEN(SplitString$)
495       END IF
496     END SELECT
497   LOOP
498   IF EndLoop = 0 THEN
499     IF LEN(TempString$) > 0 THEN
500       SplitField$(ActualIndex&) = TempString$
501     ELSEIF LastPos <= LEN(SplitString$) THEN
502       SplitField$(ActualIndex&) = MID$(SplitString$, LastPos)
503     ELSE
504       ActualIndex& = ActualIndex& - 1
505     END IF
506   END IF
507   FOR a = ActualIndex& + 1 TO LastIndex
508     SplitField$(a) = ""
509   NEXT
510   SplitCount = (ActualIndex& - StartIndex) + 1
511 END SUB
512
513 FUNCTION StrTrim$ (a$, b$)
514         StrTrim$ = StrTrimRight$(StrTrimLeft$(a$, b$), b$)
515 END FUNCTION
516
517 FUNCTION StrTrimLeft$ (a$, b$) 'public
518         p = 0
519         l = LEN(a$)
520         DO
521           p = p + 1
522           t$ = MID$(a$, p, 1)
523         LOOP WHILE (p < l) AND (INSTR(b$, t$) > 0)
524         StrTrimLeft$ = MID$(a$, p)
525 END FUNCTION
526
527 FUNCTION StrTrimRight$ (a$, b$) 'public
528         l = LEN(a$)
529         p = l + 1
530         DO
531           p = p - 1
532           IF p > 0 THEN
533             t$ = MID$(a$, p, 1)
534           ELSE
535             t$ = ""
536           END IF
537         LOOP WHILE (p > 0) AND (INSTR(b$, t$) > 0)
538         StrTrimRight$ = LEFT$(a$, p)
539 END FUNCTION
540
541 \1a