This commit is contained in:
julianb0 2019-05-30 11:19:16 +02:00
parent 29a8c50d0a
commit cc03cc8722
No known key found for this signature in database
GPG Key ID: DDF8325C95299A62
4 changed files with 110 additions and 69 deletions

View File

@ -56,6 +56,9 @@ pdata = 0
# size of .text section
ptext = 0
# for local labels
plastlabel = ''
# after parse() is done, pdata and ptext are never modified
# padding bytes between .text and .data
@ -65,11 +68,19 @@ pdata_pad = 0
def name_valid(name):
for c in name.lower():
if not(c in 'abcdefghijklmnopqrstuvwxyz0123456789[$._+]='):
if not(c in 'abcdefghijklmnopqrstuvwxyz0123456789[$._+]=,'):
print("BAD '{}'".format(c))
return False
return True
def is_number(s):
try:
int(s, base=0)
except ValueError:
return False
return True
#-------------------------------------------------------------------------------
def parse_lst_regs():
@ -148,22 +159,24 @@ def parse_preproc(line):
#-------------------------------------------------------------------------------
def apply_pdefs(line):
tok = line.split(' ')
new = '' + tok[0]
return line
"""
tok = line.split(' ', 1)
if len(tok) > 3:
print("Too many tokens in line: {}".format(line))
return False, None
# 'mov rax, rax' => 'mov rax rax'
if len(tok) == 3 and tok[1][-1] == ',':
tok[1] = tok[1][:-1]
instr = tok[0]
new = '' + tok[0]
for word in tok[1:]:
word = word.strip()
new += ' '
if word[0] == '[':
print(word)
if '[' in word:
assert(len(word) > 2)
assert(word[-1] == ']')
new += '['
assert(word[1:].strip()[0] == '[')
new += word[0] + '['
word = word[1:-1]
need_bracket = True
else:
@ -174,43 +187,54 @@ def apply_pdefs(line):
if not name_valid(word):
print("Invalid token in line: {}".format(line))
return False, None
leave()
sys.exit(1)
return None
new += word
if need_bracket:
new += ']'
return True, new
return new
"""
def parse():
global ptext
global plastlabel
for count, line in enumerate(fi):
line = line.rstrip()
if len(line) == 0:
continue
if line[0] == '#' or line[0] == ';':
for i in range(len(line)):
if line[i] in '#;@!/':
line = line[:i].rstrip()
break
if len(line) == 0:
continue
if line[0] == ' ' or line[0] == '\t':
line = line.lstrip()
if line[0] in '#;@!/':
continue
line = apply_pdefs(line)
ptext += parse_instr(line)
instrs.write("\n")
ok, line = apply_pdefs(line)
if ok:
# instrs.write("{} ".format(ptext))
ptext += parse_instr(line)
instrs.write("\n")
continue
# Preprocessor or label?
if line[-1] == ':':
if name_valid(line[:-1]):
plabels_text[line[:-1]] = ptext
label = line[:-1]
if label[0] == '.':
label = plastlabel + label
else:
plastlabel = label
plabels_text[label] = ptext
else:
print("Bad label name: {}".format(line[:-1]))
leave()
@ -221,44 +245,53 @@ def parse():
parse_preproc(line)
#-------------------------------------------------------------------------------
def is_number(s):
try:
int(s, base=0)
except ValueError:
return False
return True
def parse_instr(line):
# instrs.write(hex(ptext))
tok = line.split(' ')
if line == None or len(line) == 0:
return 0
tok = line.split(' ', 1)
instr = tok[0].strip()
if len(tok) > 1:
params = tok[1].strip()
else:
params = None
fellthrough = False
size = 2
if tok[0] == "rep":
if instr == "rep":
if params == None:
print("Missing instruction after rep prefix: {}".format(line))
leave()
sys.exit(1)
instrs.write("%rep ")
tok = tok[1:]
instr, params = params.split(' ', 1)
size += 2
instr_name = tok[0]
instr_name = instr
instr_args = ''
if len(tok) == 1:
if params == None or len(params) == 0:
instrs.write("{}".format(instr_name))
return 2 # instruction
tok = tok[1:]
tok = params.split(',')
for word in tok:
word = word.strip()
instr_args += ' '
pref = None
# memory length prefixes
if len(word) > 1 and word[1] == '[':
#print(word)
if len(word) > 2 and '[' in word:
if word[0] == 'b':
pref = "%b"
elif word[0] == 'w':
@ -272,7 +305,8 @@ def parse_instr(line):
leave()
sys.exit(1)
word = word[1:]
word = word[1:].strip()
assert(word[0] == '[')
# [reg+off] or [imm64]
if word[0] == '[':
@ -294,13 +328,10 @@ def parse_instr(line):
assert(len(word) > 3)
reg, off = word.strip().split('+', 1)
reg, off = word.split('+', 1)
reg = reg.strip()
off = off.strip()
print(reg)
print(off)
instr_args += "{} {}".format(off, reg)
continue
@ -323,7 +354,13 @@ def parse_instr(line):
instr_args += word
fellthrough = False
continue
# preprocessor
if word in pdefs:
word = pdefs[word]
# Fall through
# register
if word in pregs:
size += 2
if not fellthrough:
@ -338,6 +375,10 @@ def parse_instr(line):
if not fellthrough:
instr_name += "_i"
instr_args += "%imm64 "
if word[0] == '.':
instr_args += plastlabel
instr_args += word
fellthrough = False
@ -366,7 +407,7 @@ special_syms = {
def gentext():
instrs.seek(0)
text_start = 0 # 0x100000
text_start = 0x100000
data_start = text_start + ptext
data_start += (8 - data_start % 8)

View File

@ -3,8 +3,6 @@
hw = "Hello World"
;
; void main(void)
;
; Entry point
;
@ -15,6 +13,7 @@ main:
mov ax0, hw
call print
stop
;
@ -22,8 +21,6 @@ main:
;
v_print_max := 0xFF
;
; void print(char *)
;
; Print a string
;
@ -31,19 +28,17 @@ print:
enter
mov rcx, v_print_max
.p1:
test b[ax0], b[ax0]
jz .p2
.1:
test b[ax0], b [ ax0 + 0 ]
jz .2
prn b[ax0]
inc ax0
loop .p1
loop .1
.p2:
.2:
leave
ret
;
; void print_n(char *, int)
;
; Print exactly ax1 characters
;
@ -51,10 +46,10 @@ print_n:
enter
mov rcx, ax1
.pn1:
.1:
prn b[ax0]
inc ax0
loop .pn1
loop .1
leave
ret

View File

@ -122,9 +122,9 @@ void disasm(ctx_t *ctx)
#else
do_rep:
dumpinstr(ctx, rip, rep, c, &p1, &p2);
i->func(ctx, &p1, &p2);
dumpinstr(ctx, rip, rep, c, &p1, &p2);
if (rep && ctx->r[RCX].val > 0) {
log("rcx::%lu\n", ctx->r[RCX].val);

View File

@ -10,9 +10,11 @@ reg_t arch_r[NREGS] =
{ "rip", "Instruction pointer", "Special; Volatile", 0, RES },
{ "flg", "Flags register", "Special; Volatile", 0, RES },
// Stack registers
{ "rbp", "Stack base", "Special; Non-volatile", 0, GPR },
{ "rsp", "Stack pointer", "Special; Non-volatile", 0, GPR },
// General-purpose volatile registers
{ "rax", "Accumulator 0", "Volatile", 0, GPR },
{ "rbx", "Accumulator 1", "Volatile", 0, GPR },
{ "rcx", "Accumulator 2", "Volatile", 0, GPR },
@ -22,6 +24,7 @@ reg_t arch_r[NREGS] =
{ "rdi", "Accumulator 6", "Volatile", 0, GPR },
{ "rsi", "Accumulator 7", "Volatile", 0, GPR },
// General-purpose non-volatile registers
{ "nx0", "Accumulator 8", "Non-volatile", 0, GPR },
{ "nx1", "Accumulator 9", "Non-volatile", 0, GPR },
{ "nx2", "Accumulator 10", "Non-volatile", 0, GPR },
@ -30,7 +33,8 @@ reg_t arch_r[NREGS] =
{ "nx5", "Accumulator 13", "Non-volatile", 0, GPR },
{ "nx6", "Accumulator 14", "Non-volatile", 0, GPR },
{ "nx7", "Accumulator 15", "Non-volatile", 0, GPR },
// Argument registers; volatile
{ "ax0", "Argument 0", "Volatile", 0, GPR },
{ "ax1", "Argument 1", "Volatile", 0, GPR },
{ "ax2", "Argument 2", "Volatile", 0, GPR },
@ -44,18 +48,19 @@ reg_t arch_r[NREGS] =
{ "cr0", "Control register 0", "Control", 0, CTL },
// cr1: code offset
{ "cr1", "Control register 1", "Control", 0x100000, CTL },
{ "cr1", "Control register 1", "Control", 0, CTL },
// cr2: data offset
{ "cr2", "Control register 2", "Control", 0x100000, CTL },
{ "cr2", "Control register 2", "Control", 0, CTL },
// unused
// Unused
{ "cr3", "Control register 3", "Control", 0, CTL },
{ "cr4", "Control register 4", "Control", 0, CTL },
{ "cr5", "Control register 5", "Control", 0, CTL },
{ "cr6", "Control register 6", "Control", 0, CTL },
{ "cr7", "Control register 7", "Control", 0, CTL },
// System-reserved
{ "sa0", "Supervisor acc. 0", "System; Non-volatile", 0, SYS },
{ "sa1", "Supervisor acc. 1", "System; Non-volatile", 0, SYS },
{ "sa2", "Supervisor acc. 2", "System; Non-volatile", 0, SYS },