mpir/build.vc9/g2y.py
2009-01-08 14:51:11 +00:00

396 lines
11 KiB
Python

from __future__ import print_function
import string, re, os, sys, shutil
# regular expression for registers
r_q = r"(?:r[abcd]x|r[sd]i|r[bsi]p)|(?:r8|r9|r1[012345])|"
r_d = r"(?:e[abcd]x|e[sd]i|e[bsi]p|r[89]d|r1[012345]d)|"
r_w = r"(?:[abcd]x|[sd]i|[bsi]p|r[89]w|r1[012345]w)|"
r_b = r"(?:[abcd]l|[ds]il|[bsi]pl|r[89]l|r1[012345]l)|"
r_x = r"(?:mm\d|mm1[0-5])|(?:mmx\d|mmx1[0-5])|(?:st\([0-7]\))"
p_rg = r"(?:\s*%(" + r_b + r_w + r_d + r_q + r_x + r"))"
# regular expression for dis(r1, r2, mul) forms
p_mu = r"(?:\s*,\s*([1248])){0,1}\s*(?=\))"
p_di = r"(?:\s*([\+\-]{0,1}[0-9]*)(?=\()){0,1}"
p_t1 = p_di + r"\s*\(" + p_rg + r"(?:\s*\)|\s*,*" + p_rg + p_mu + r"\s*\))"
# regular expression for immediate (numeric, not symbolic)
p_im = r"\s+\`{0,1}\$\'{0,1}([\+\-]{0,1}[a-zA-Z0-9]+)"
# regular expression for labels
p_la = r"\s*([a-zA-Z$_][a-zA-Z0-9\$_]*|\.[0-9]+)(:)"
p_lr = r"\s+([a-zA-Z$_][a-zA-Z0-9\$_]*|\.[0-9]+)"
# regular expression for instructions
p_in = r"\s*([a-zA-Z][a-zA-Z0-9]*)"
m_f1 = re.compile(p_in + p_rg + r"\s*," + p_t1)
m_f2 = re.compile(p_in + p_t1 + r"\s*," + p_rg)
m_f3 = re.compile(p_in + p_t1)
m_f4 = re.compile(p_in + p_im + r"\s*," + p_t1)
m_f5 = re.compile(p_in + p_im + r"\s*," + p_rg)
m_f6 = re.compile(p_in + p_rg + r"\s*," + p_rg)
m_f7 = re.compile(p_in + p_rg)
m_f8 = re.compile(p_in + p_im)
m_f9 = re.compile(p_in + p_lr)
m_la = re.compile(p_la)
r_mac = re.compile(r"^\s*(?:define|DEFINE)\s*\(\s*`"
"([A-Z$_][A-Z0-9$_]*)'\s*,\s*`\s*$")
r_mnd = re.compile(r"^\s*'\s*\)\s*$")
r_dlr = re.compile(r"\$([0-9]+)")
r1 = r"\s*(\%{0,1}[0-9]+){0,1}\s*"
r2 = r"(?:,\s*(\%{0,1}[0-9]+))?\s*"
r_mrf = re.compile(r"([A-Z$_][A-Z0-9$_]*)\s*\(" + r1 + r2 +
r2 + r2 + r2 + r2 + r2 + r2 + r2 + r2 + r"\)")
def pass_one(code) :
labels = []
for l in code :
m = m_la.search(l)
if m :
labels += [m.group(1)]
return labels
def pass_two(code, labels) :
mac_name = ''
mac_dict = {}
lab_idx = 0
for ln in range(len(code)) :
l = code[ln]
m = r_mac.search(l)
if m and not mac_name :
mac_name = m.group(1)
mac_dict[mac_name] = [ln, 0, 0, {}]
continue
m = r_mnd.search(l)
if m and mac_name:
mac_dict[mac_name][1] = ln
mac_name = ''
lab_idx = 0
continue
if mac_name :
m = r_dlr.findall(l)
if m :
mn = max(int(i) for i in m)
if mn > mac_dict[mac_name][2] :
mac_dict[mac_name][2] = mn
m = m_la.search(l)
if m and m.group(1) in labels :
lab_idx += 1
mac_dict[mac_name][3][m.group(1)] = lab_idx
return mac_dict
def proc_m(m, i, j) :
v = list(m.groups())
n = len(v)
if n <= i :
return ([], '')
ss = (v[i] if not v[i] or v[i][0] in '+-' else '+' + v[i]) + ']'
if n > i + 3 and i + 3 < j and v[i + 3] :
ss = ('' if not v[i + 3] else '*' + v[i + 3]) + ss
if n > i + 2 and i + 2 < j and v[i + 2] :
ss = '+' + v[i + 2] + ss
if n > i + 1 and i + 1 < j and v[i + 1] :
ss = v[i + 1] + ss
return (v[ 0 : i ] + v[ j : ], '[' + ss)
def pass_three(code, labels, macros) :
lo = []
debug = False
dot_labels = False
mac_name = ''
for l in code :
lp = '\n'
# labels
m = m_la.search(l)
if m :
l = l[ m.end(2) : -1 ]
if mac_name :
if m.group(1) in macros[mac_name][3] :
ii = macros[mac_name][3][m.group(1)]
else :
print("internal error")
else :
ii = labels.index(m.group(1))
lab = re.sub('\$', '%', m.group(1))
if not l :
if mac_name :
lo += ['\n%%{0}:'.format(ii)]
elif dot_labels :
lo += ['\n.{0}:'.format(ii)]
else :
lo += ['\n{0}:'.format(lab)]
continue
else :
if mac_name :
lp = '\n%%{0}:'.format(ii)
elif dot_labels :
lp = '\n.{0}:'.format(ii)
else :
lp = '\n{0}:'.format(lab)
m = re.search(r"(\s*)#\s*(.*)", l)
if m :
v = list(m.groups())
lo += [lp + '{0[0]}; {0[1]}'.format(v)]
continue
m = re.search(r"dnl(.*)", l)
if m :
lo += [lp + ';{0}'.format(m.group(1))]
continue
# ins reg, dis(reg, reg, off)
m = m_f1.search(l)
if m :
if debug :
print(l, end = '')
v, s = proc_m(m, 2, 6)
lo += [lp + '\t{0[0]:7s} {1}, {0[1]}'.format(v, s)]
continue
# ins dis(reg, reg, off), reg
m = m_f2.search(l)
if m :
if debug :
print(l, end = '')
v, s = proc_m(m, 1, 5)
lo += [lp + '\t{0[0]:7s} {0[1]}, {1}'.format(v, s)]
continue
# ins dis(reg, reg, off)
m = m_f3.search(l)
if m :
if debug :
print(l, end = '')
v, s = proc_m(m, 1, 5)
lo += [lp + '\t{0[0]:7s} {1}'.format(v, s)]
continue
# ins imm, dis(reg, reg, off)
m = m_f4.search(l)
if m :
if debug :
print(l, end = '')
v, s = proc_m(m, 2, 6)
lo += [lp + '\t{0[0]:7s} {1}, {0[1]}'.format(v, s)]
continue
# ins imm, reg
m = m_f5.search(l)
if m :
v = list(m.groups())
if debug :
print(l, end = '')
lo += [lp + '\t{0[0]:7s} {0[2]}, {0[1]}'.format(v)]
continue
# ins reg, reg
m = m_f6.search(l)
if m :
v = list(m.groups())
if debug :
print(l, end = '')
lo += [lp + '\t{0[0]:7s} {0[2]}, {0[1]}'.format(v)]
continue
# ins reg
m = m_f7.search(l)
if m :
v = list(m.groups())
if debug :
print(l, end = '')
lo += [lp + '\t{0[0]:7s} {0[1]}'.format(v)]
continue
# ins imm
m = m_f8.search(l)
if m :
v = list(m.groups())
if debug :
print(l, end = '')
lo += [lp + '\t{0[0]:7s} {0[1]}'.format(v)]
continue
# jump label
m = m_f9.search(l)
if m :
v = list(m.groups())
if v[1] in labels :
if debug :
print(l, end = '')
if mac_name and v[1] in macros[mac_name][3] :
ii = macros[mac_name][3][v[1]]
lo += [lp + '\t{0[0]:7s} %%{1}'.format(v, ii)]
continue
if dot_labels :
ii = labels.index(v[1])
lo += [lp + '\t{0[0]:7s} .{1}'.format(v, ii)]
else :
lab = re.sub('\$', '%', v[1])
lo += [lp + '\t{0[0]:7s} {1}'.format(v, lab)]
continue
# macro definitions
m = r_mac.search(l)
if m :
mac_name = m.group(1)
if mac_name in macros :
lo += [lp + '%macro ' + mac_name.lower() + ' '
+ str(macros[mac_name][2])]
continue
m = r_mnd.search(l)
if m and mac_name :
mac_name = ''
lab_ofs = 0
lo += [lp + "%endmacro"]
continue
m = r_dlr.findall(l)
if m :
l = re.sub(r"\$([0-9]+)", r"%\1", l)
m = re.search("PROLOGUE\(([a-zA-Z$_][a-zA-Z0-9$_]*)\)", l)
if m :
lo += [lp + "\twin64_gcc_start {0}".format(m.group(1))]
continue
m = re.search("EPILOGUE\(\)", l)
if m :
lo += [lp + "\twin64_gcc_end"]
continue
# macro calls
m = r_mrf.search(l)
if m :
if m.group(1).lower() == 'align' :
lo += [lp + '\talign {0}'.format(m.group(2))]
continue
elif m.group(1) in macros :
lp += '\t{0:7s}'.format(m.group(1).lower())
i = 2
while i <= m.lastindex and m.group(i) :
lp += ' {0}'.format(m.group(i))
i += 1
lo += [lp]
continue
elif m.group(1) and not m.group(2) :
lo += [lp + '\t{0}'.format(m.group(1))]
continue
if mac_name :
m = re.search(r"\s*([^%]+)%([0-9]+)\s*", l)
if m and m.lastindex == 2 and int(m.group(2)) <= macros[mac_name][2] :
lo += [lp + '\t{0}%{1}'.format(m.group(1).lower(),m.group(2))]
continue
# ins
m = re.search(p_in + r"\s+(.*)", l)
if m :
v = list(m.groups())
if debug :
print(l, end = '')
if len(v) == 1 or len(v) == 2 and v[1] == '' :
lo += [lp + '\t{0[0]}'.format(v)]
continue
elif v[0] == 'C' :
lo += [lp + ';\t{0}'.format(v[1])]
continue
m = re.search(r"\s*(\S+)", l)
if m :
lo += [lp + '{0} ; < not translated >'.format(l[:-1])]
else :
lo += ['']
return lo
def form_path(p) :
n = string.rfind(p, '\\', 0, -1)
if n != -1 :
if not os.path.exists(p[ : n + 1]) :
form_path(p[ : n + 1])
if p[-1] == '\\' and not os.path.exists(p) :
os.mkdir(p)
def convert(s, d, l) :
fd = os.listdir(s)
for f in fd :
sp = os.path.join(s,f)
dp = os.path.join(d,f)
if os.path.isdir(sp) :
convert(sp, dp, l + 1)
elif os.path.isfile(sp) :
if sp != dp and os.path.exists(dp) :
continue
fn = os.path.basename(f)
x = os.path.splitext(fn)
if x[1] == '.asm' :
form_path(dp)
print("translating '{0}'".format(sp))
f = open(sp, "r")
code = f.readlines()
f.close()
if sp == dp :
rp = os.path.join(s, x[0] + '.old')
os.rename(sp, rp)
labels = pass_one(code)
macros = pass_two(code, labels)
code = pass_three(code, labels, macros)
f = open(dp, "w")
f.writelines(code)
f.close()
elif False :
form_path(dp)
shutil.copyfile(sp, dp)
cd = os.getcwd() # it must run in build.vc9
if cd.endswith("build.vc9") :
cd1 = cd + "\\..\\mpn\\x86_64" # the GCC assembler directory
cd2 = cd + "\\..\\mpn\\x86_64w" # the YASM (Windows) assembler directory
elif cd.endswith("x86_64") :
if os.path.exists(cd + "\\..\\x86_64w") :
cd1 = cd
cd2 = cd + "\\..\\x86_64w"
else :
cd1 = cd2 = cd
else:
cd1 = cd2 = None
if cd1 and os.path.exists(cd1) :
if os.path.exists(cd2) :
print("warning: output directory '{0}' already exists".format(cd2))
convert(cd1, cd2, 0) # convert format from GAS to YASM
elif cd1 :
print("cannot find input directory: '{0}'".format(cd1))
else :
# for testing -- translates to directory amd64c rather than amd64
f = open("..\\mpn\\x86_64\\amd64\\mul_basecase.asm", "r")
code = f.readlines()
f.close()
labels = pass_one(code)
macros = pass_two(code, labels)
code = pass_three(code, labels, macros)
f = open("..\\mpn\\x86_64w\\amd64c\\mul_basecase.asm", "w")
f.writelines(code)
f.close()