nasm/insns.bas
H. Peter Anvin 87bc61964c NASM 0.97
2002-04-30 20:53:16 +00:00

536 lines
No EOL
13 KiB
QBasic
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

' INFO_1: Converter for INSNS.DAT to INSNSA.C and INSNSD.C
'
' INFO_2: Written by Mark Junker in 1997
' InterNet: mjs@prg.hannover.sgh-net.de
' FIDO: Mark Junker@2:2437/47.21
'
' COMMENT: While I wrote this program I often asked me, if it isn't easier
' to write an interpreter for pearl-scripts :]
'
' COMMENT: To start the program press SHIFT+F5 within the QBasic IDE
' or start it from the command-line with QBASIC /RUN MACROS
'
DEFINT A-Z
DECLARE FUNCTION ReplaceOp$ (a$)
DECLARE FUNCTION StrTrimLeft$ (a$, b$)
DECLARE FUNCTION StrTrimRight$ (a$, b$)
DECLARE FUNCTION StrTrim$ (a$, b$)
DECLARE SUB StrSplitString (SplitString$, SplitChars$, SplitField$(), SplitCount%)
DECLARE FUNCTION Min% (a%, b%)
DECLARE FUNCTION StrInstrLeft% (SearchStart%, SearchIn$, SearchFor$)
DECLARE FUNCTION StrAscii% (a$)
CONST MaxOpCodeBase = 3
CONST MaxOpCodeType = 8
CLS
DIM LineData$(1 TO 2)
DIM StrucData$(1 TO 5)
DIM OpCodeList$(0 TO 255)
DIM OpCodeByte(1 TO MaxOpCodeType, 1 TO MaxOpCodeBase)
DIM OpCodeStat(1 TO 10) ' don't need mode :)
Instructs$ = ""
LineOfs$ = ""
OPEN "I", 1, "insns.dat"
OPEN "B", 3, "insns.tmp"
qt$ = CHR$(34)
crlf$ = CHR$(13) + CHR$(10)
'
' preprocessing the current file
'
HexChar$ = "0123456789ABCDEF"
PRINT "Preprocessing INSNS.DAT"
OpCodes = 0
OpCodeDebug = 0
NowLineOfs& = 1
lineNr = 0
WHILE NOT EOF(1)
lineNr = lineNr + 1
IF (lineNr AND 15) = 0 THEN
LOCATE , 1
PRINT lineNr, OpCodes, OpCodeDebug;
END IF
LINE INPUT #1, l$
CALL StrSplitString(l$, ";", LineData$(), SplitCount)
IF SplitCount THEN
LineData$(1) = StrTrim$(LineData$(1), CHR$(9) + " ")
IF LEN(LineData$(1)) THEN
CALL StrSplitString(LineData$(1), " ", StrucData$(), cntSplit)
IF cntSplit <> 4 THEN
PRINT "line"; lineNr; " does not contain four fields"
END
END IF
tst$ = UCASE$(StrucData$(2))
res$ = ""
cnt% = 1
isfirst = 1
op = 1
p = StrInstrLeft(1, tst$ + ",", "|:,")
WHILE p
h$ = ReplaceOp$(MID$(tst$, op, p - op))
IF LEN(h$) THEN
SELECT CASE MID$(tst$, p, 1)
CASE ""
IF isfirst THEN
res$ = res$ + h$
ELSE
res$ = res$ + "|" + h$
END IF
isfirst = 0
CASE ","
IF isfirst THEN
res$ = res$ + h$ + ","
ELSE
res$ = res$ + "|" + h$ + ","
END IF
cnt% = cnt% + 1
isfirst = 1
CASE "|"
IF isfirst THEN
res$ = res$ + h$
ELSE
res$ = res$ + "|" + h$
END IF
isfirst = 0
CASE ":"
res$ = res$ + h$ + "|COLON,"
cnt% = cnt% + 1
END SELECT
END IF
op = p + 1
p = StrInstrLeft(op, tst$ + ",", "|:,")
WEND
FOR a = cnt% + 1 TO 3
res$ = res$ + ",0"
NEXT
StrucData$(2) = res$
IF LEFT$(res$, 2) = "0," THEN cnt% = cnt% - 1
StrucData$(5) = LTRIM$(STR$(cnt%))
NoDebug = 0
res$ = ""
tst$ = UCASE$(StrucData$(4))
op = 1
p = INSTR(tst$ + ",", ",")
isfirst = 1
WHILE p
h$ = MID$(tst$, op, p - op)
IF h$ = "ND" THEN
NoDebug = 1
ELSE
IF isfirst THEN
res$ = res$ + "IF_" + h$
ELSE
res$ = res$ + "|IF_" + h$
END IF
isfirst = 0
END IF
op = p + 1
p = INSTR(op, tst$ + ",", ",")
WEND
StrucData$(4) = res$
tst$ = UCASE$(StrucData$(3))
SELECT CASE tst$
CASE "IGNORE"
GOTO skipOpCode
CASE "\0", "\340"
OpCodeDebug = OpCodeDebug + 1 ' don't forget to increment
GOTO skipOpCode
END SELECT
AddRegs = 0
AddCCode = 0
NextIsOpCode = 0
opCodeVal$ = ""
op = 1
p = INSTR(tst$ + "\", "\")
DO WHILE p
h$ = MID$(tst$, op, p - op)
IF LEFT$(h$, 1) = "X" THEN
opCodeVal$ = CHR$(VAL("&H" + MID$(h$, 2)))
EXIT DO
ELSE
SELECT CASE h$
CASE "1", "2", "3"
NextIsOpCode = 1
CASE "4"
opCodeVal$ = CHR$(&H7) + CHR$(&H17) + CHR$(&H1F)
EXIT DO
CASE "5"
opCodeVal$ = CHR$(&HA1) + CHR$(&HA9)
EXIT DO
CASE "6"
opCodeVal$ = CHR$(&H6) + CHR$(&HE) + CHR$(&H16) + CHR$(&H1E)
EXIT DO
CASE "7"
opCodeVal$ = CHR$(&HA0) + CHR$(&HA8)
EXIT DO
CASE "10", "11", "12"
NextIsOpCode = 1
AddRegs = VAL(h$) - 9
CASE "330"
NextIsOpCode = 1
AddCCode = VAL(h$) - 329
CASE "17"
opCodeVal$ = CHR$(0)
EXIT DO
CASE ELSE
IF NextIsOpCode THEN
PRINT "Line:"; lineNr
PRINT "Unknown value: " + h$
END
END IF
END SELECT
END IF
op = p + 1
p = INSTR(op, tst$ + "\", "\")
LOOP
IF (p = 0) THEN
PRINT "No opcode found in line"; lineNr
PRINT "Line:"
PRINT l$
END
END IF
IF NoDebug = 0 THEN
FOR a = 1 TO LEN(opCodeVal$)
h = ASC(MID$(opCodeVal$, a, 1))
OpCodeStr$ = MKI$(OpCodeDebug)
IF AddRegs THEN
EndNr = 7
ELSEIF AddCCode THEN
EndNr = 15
ELSE
EndNr = 0
END IF
FOR b = 0 TO EndNr
OpCodeList$(h + b) = OpCodeList$(h + b) + OpCodeStr$
NEXT
NEXT
OpCodeDebug = OpCodeDebug + 1
END IF
skipOpCode:
OpCodes = OpCodes + 1
LineOfs$ = LineOfs$ + MKL$(NowLineOfs&)
LineLg = 1
h$ = CHR$(NoDebug)
PUT #3, NowLineOfs&, h$
NowLineOfs& = NowLineOfs& + 1
FOR a = 1 TO 5
lg = LEN(StrucData$(a))
h$ = CHR$(lg) + StrucData$(a)
PUT #3, NowLineOfs&, h$
NowLineOfs& = NowLineOfs& + lg + 1
LineLg = LineLg + lg + 1
NEXT
LineOfs$ = LineOfs$ + MKI$(LineLg)
END IF
END IF
WEND
LOCATE , 1
PRINT lineNr, OpCodes, OpCodeDebug
'
' creating insnsa.c
'
PRINT "Creating INSNSA.C"
OPEN "O", 2, "insnsa.c"
strBegStart$ = "static struct itemplate instrux_"
strBegEnd$ = "[] = {"
strEnd$ = " {-1}" + crlf$ + "};" + crlf$
PRINT #2, "/* This file auto-generated from insns.dat by insns.bas - don't edit it */"
PRINT #2, ""
PRINT #2, "#include <stdio.h>"
PRINT #2, "#include " + qt$ + "nasm.h" + qt$
PRINT #2, "#include " + qt$ + "insns.h" + qt$
PRINT #2, ""
oldOpCode$ = ""
pOfs = 1
FOR a = 1 TO OpCodes
LineOfs& = CVL(MID$(LineOfs$, pOfs, 4))
l$ = SPACE$(CVI(MID$(LineOfs$, pOfs + 4, 2)))
pOfs = pOfs + 6
GET #3, LineOfs&, l$
' split data into fields
NoDebug = ASC(LEFT$(l$, 1))
pLn = 2
FOR b = 1 TO 5
lgLn = ASC(MID$(l$, pLn, 1))
StrucData$(b) = MID$(l$, pLn + 1, lgLn)
pLn = pLn + lgLn + 1
NEXT
IF oldOpCode$ <> StrucData$(1) THEN
Instructs$ = Instructs$ + StrucData$(1) + CHR$(0)
IF LEN(oldOpCode$) THEN PRINT #2, strEnd$
PRINT #2, strBegStart$ + StrucData$(1) + strBegEnd$
oldOpCode$ = StrucData$(1)
END IF
SELECT CASE UCASE$(StrucData$(3))
CASE "IGNORE"
CASE ELSE
PRINT #2, " {I_" + oldOpCode$ + ", " + StrucData$(5) + ", {" + StrucData$(2) + "}, " + qt$ + StrucData$(3) + qt$ + ", " + StrucData$(4) + "},"
END SELECT
NEXT
IF LEN(oldOpCode$) THEN PRINT #2, strEnd$
PRINT #2, "struct itemplate *nasm_instructions[] = {"
op = 1
p = INSTR(Instructs$, CHR$(0))
WHILE p
h$ = MID$(Instructs$, op, p - op)
PRINT #2, " instrux_" + h$ + ","
op = p + 1
p = INSTR(op, Instructs$, CHR$(0))
WEND
PRINT #2, "};"
CLOSE 2
'
' creating insnsd.c
'
PRINT "Creating INSNSD.C"
OPEN "O", 2, "insnsd.c"
PRINT #2, "/* This file auto-generated from insns.dat by insns.bas - don't edit it */"
PRINT #2, ""
PRINT #2, "#include <stdio.h>"
PRINT #2, "#include " + qt$ + "nasm.h" + qt$
PRINT #2, "#include " + qt$ + "insns.h" + qt$
PRINT #2, ""
PRINT #2, "static struct itemplate instrux[] = {"
pOfs = 1
FOR a = 1 TO OpCodes
LineOfs& = CVL(MID$(LineOfs$, pOfs, 4))
l$ = SPACE$(CVI(MID$(LineOfs$, pOfs + 4, 2)))
pOfs = pOfs + 6
GET #3, LineOfs&, l$
' split data into fields
NoDebug = ASC(LEFT$(l$, 1))
pLn = 2
FOR b = 1 TO 5
lgLn = ASC(MID$(l$, pLn, 1))
StrucData$(b) = MID$(l$, pLn + 1, lgLn)
pLn = pLn + lgLn + 1
NEXT
IF NoDebug OR (UCASE$(StrucData$(3)) = "IGNORE") THEN
' ignorieren
ELSE
PRINT #2, " {I_" + StrucData$(1) + ", " + StrucData$(5) + ", {" + StrucData$(2) + "}, " + qt$ + StrucData$(3) + qt$ + ", " + StrucData$(4) + "},"
END IF
NEXT
PRINT #2, " {-1}" + crlf$ + "};" + crlf$
OpCodeBegS$ = "static struct itemplate *itable_"
OpCodeBegE$ = "[] = {"
OpCodeEnd$ = " NULL" + crlf$ + "};" + crlf$
FOR a = 0 TO 255
PRINT #2, OpCodeBegS$ + RIGHT$("00" + HEX$(a), 2) + OpCodeBegE$
h$ = OpCodeList$(a)
FOR b = 1 TO LEN(h$) STEP 2
OpCodePos = CVI(MID$(h$, b, 2))
PRINT #2, " instrux +" + STR$(OpCodePos) + ","
NEXT
PRINT #2, OpCodeEnd$
NEXT
PRINT #2, "struct itemplate **itable[] = {"
FOR a = 0 TO 255
PRINT #2, " itable_" + RIGHT$("00" + HEX$(a), 2) + ","
NEXT
PRINT #2, "};"
CLOSE 2
CLOSE 3
KILL "insns.tmp"
CLOSE 1
SYSTEM
FUNCTION ReplaceOp$ (a$)
tst$ = UCASE$(a$)
SELECT CASE tst$
' CASE "ND"
' ReplaceOp$ = ""
CASE "VOID", ""
ReplaceOp$ = "0"
CASE "IMM"
ReplaceOp$ = "IMMEDIATE"
CASE "MEM"
ReplaceOp$ = "MEMORY"
CASE "MEM8", "MEM16", "MEM32", "MEM64", "MEM80"
ReplaceOp$ = "MEMORY|BITS" + MID$(tst$, 4)
CASE "REG8", "REG16", "REG32"
ReplaceOp$ = tst$
CASE "RM8", "RM16", "RM32"
ReplaceOp$ = "REGMEM|BITS" + MID$(tst$, 3)
CASE "IMM8", "IMM16", "IMM32"
ReplaceOp$ = "IMMEDIATE|BITS" + MID$(tst$, 4)
CASE ELSE
ReplaceOp$ = tst$
END SELECT
END FUNCTION
FUNCTION Min% (a%, b%)
IF a% < b% THEN Min% = a% ELSE Min% = b%
END FUNCTION
FUNCTION StrAscii (a$)
IF LEN(a$) = 0 THEN
StrAscii = -1
ELSE
StrAscii = ASC(a$)
END IF
END FUNCTION
' same as =INSTR(SearchStart, SearchIn, ANY SearchFor$) in PowerBASIC(tm)
'
FUNCTION StrInstrLeft (SearchStart, SearchIn$, SearchFor$)
ValuesCount = LEN(SearchFor$)
MaxValue = LEN(SearchIn$) + 1
MinValue = MaxValue
FOR Counter1 = 1 TO ValuesCount
SearchChar$ = MID$(SearchFor$, Counter1, 1)
hVal2 = INSTR(SearchStart, SearchIn$, SearchChar$)
IF hVal2 > 0 THEN MinValue = Min%(hVal2, MinValue)
NEXT
IF MinValue = MaxValue THEN MinValue = 0
StrInstrLeft = MinValue
END FUNCTION
'
' This is a very damn fuckin' shit version of this splitting routine.
' At this time, it's not very useful :]
'
SUB StrSplitString (SplitString$, SplitChars$, SplitField$(), SplitCount)
StartIndex = LBOUND(SplitField$)
LastIndex = UBOUND(SplitField$)
ActualIndex& = StartIndex
SplitCount = 0
LastPos = 1
FoundPos = StrInstrLeft(LastPos, SplitString$, SplitChars$ + CHR$(34))
GetDirect = 0
EndLoop = 0
TempString$ = ""
DO WHILE FoundPos > 0
FoundCharVal = StrAscii(MID$(SplitString$, FoundPos, 1))
PosDiff = (FoundPos - LastPos) + 1
SELECT CASE FoundCharVal
CASE 34
TempString$ = TempString$ + MID$(SplitString$, LastPos, PosDiff - 1)
SELECT CASE EndLoop
CASE 0
EndLoop = 2
CASE 3
EndLoop = 0
END SELECT
CASE ELSE
TempString$ = TempString$ + MID$(SplitString$, LastPos, PosDiff - 1)
SplitField$(ActualIndex&) = TempString$
TempString$ = ""
ActualIndex& = ActualIndex& + 1
IF ActualIndex& > LastIndex THEN
ActualIndex& = LastIndex
EndLoop = 1
END IF
END SELECT
SELECT CASE EndLoop
CASE 0
DO
LastPos = FoundPos + 1
FoundPos = StrInstrLeft(LastPos, SplitString$, SplitChars$)
LOOP WHILE LastPos = FoundPos
FoundPos = StrInstrLeft(LastPos, SplitString$, SplitChars$ + CHR$(34))
CASE 1
FoundPos = 0
LastPos = LEN(SplitString$) + 1
CASE 2
EndLoop = 3
LastPos = FoundPos + 1
FoundPos = StrInstrLeft(LastPos, SplitString$, CHR$(34))
IF FoundPos = 0 THEN
SplitString$ = SplitString$ + CHR$(34)
FoundPos = LEN(SplitString$)
END IF
END SELECT
LOOP
IF EndLoop = 0 THEN
IF LEN(TempString$) > 0 THEN
SplitField$(ActualIndex&) = TempString$
ELSEIF LastPos <= LEN(SplitString$) THEN
SplitField$(ActualIndex&) = MID$(SplitString$, LastPos)
ELSE
ActualIndex& = ActualIndex& - 1
END IF
END IF
FOR a = ActualIndex& + 1 TO LastIndex
SplitField$(a) = ""
NEXT
SplitCount = (ActualIndex& - StartIndex) + 1
END SUB
FUNCTION StrTrim$ (a$, b$)
StrTrim$ = StrTrimRight$(StrTrimLeft$(a$, b$), b$)
END FUNCTION
FUNCTION StrTrimLeft$ (a$, b$) 'public
p = 0
l = LEN(a$)
DO
p = p + 1
t$ = MID$(a$, p, 1)
LOOP WHILE (p < l) AND (INSTR(b$, t$) > 0)
StrTrimLeft$ = MID$(a$, p)
END FUNCTION
FUNCTION StrTrimRight$ (a$, b$) 'public
l = LEN(a$)
p = l + 1
DO
p = p - 1
IF p > 0 THEN
t$ = MID$(a$, p, 1)
ELSE
t$ = ""
END IF
LOOP WHILE (p > 0) AND (INSTR(b$, t$) > 0)
StrTrimRight$ = LEFT$(a$, p)
END FUNCTION