191 lines
6.7 KiB
Text
191 lines
6.7 KiB
Text
-- demo\rosetta\Compiler\cgen.exw
|
|
-- Generates 32-bit machine code (see note in vm.exw)
|
|
without js -- (machine code!)
|
|
include cgen.e
|
|
|
|
function get_var_name(atom addr)
|
|
integer n = (addr-var_mem)/4+1
|
|
if n<1 or n>length(vars) then ?9/0 end if
|
|
return vars[n]
|
|
end function
|
|
|
|
function hxl(integer pc, object oh, string fmt, sequence args={})
|
|
-- helper routine to display the octal/hex bytes just decoded,
|
|
-- along with the code offset and the human-readable text.
|
|
if length(args) then fmt = sprintf(fmt,args) end if
|
|
sequence octhex = {}
|
|
atom base = code_mem+pc
|
|
integer len = 0
|
|
if integer(oh) then -- all octal
|
|
for i=1 to oh do
|
|
octhex = append(octhex,sprintf("0o%03o",peek(base)))
|
|
base += 1
|
|
end for
|
|
len = oh
|
|
else -- some octal and some hex
|
|
for i=1 to length(oh) by 2 do
|
|
for j=1 to oh[i] do
|
|
octhex = append(octhex,sprintf("0o%03o",peek(base)))
|
|
base += 1
|
|
end for
|
|
len += oh[i]
|
|
for j=1 to oh[i+1] do
|
|
octhex = append(octhex,sprintf("#%02x",peek(base)))
|
|
base += 1
|
|
end for
|
|
len += oh[i+1]
|
|
end for
|
|
end if
|
|
printf(output_file,"%4d: %-30s %s\n",{pc+1,join(octhex,","),fmt})
|
|
return len
|
|
end function
|
|
|
|
constant cccodes = {"o?" ,"no?","b?" ,"ae?","z" ,"ne" ,"be?","a?",
|
|
-- 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 ,
|
|
"s?" ,"ns?","pe?","po?","l" ,"ge" ,"le" ,"g" }
|
|
-- 8 , 9 , 10 , 11 , 12 , 13 , 14 , 15
|
|
|
|
constant regs = {"eax","ecx","edx"} -- (others as/when needed)
|
|
|
|
procedure decode()
|
|
-- for a much more complete (and better organised) disassembler, see p2asm.e
|
|
integer pc = 0, -- nb 0-based
|
|
opcode, xrm
|
|
|
|
while pc<length(code) do
|
|
opcode = peek(code_mem+pc)
|
|
xrm = -1
|
|
switch opcode do
|
|
case 0o150:
|
|
atom vaddr = peek4s(code_mem+pc+1)
|
|
integer n = find(vaddr,stringptrs)
|
|
object arg = iff(n?enquote(strings[n])
|
|
:sprintf("%d",vaddr))
|
|
pc += hxl(pc,{1,4},"push %s",{arg})
|
|
case 0o217:
|
|
case 0o377:
|
|
integer n = find(opcode,{0o217,0o377})
|
|
string op = {"pop","push"}[n]
|
|
xrm = peek(code_mem+pc+1)
|
|
if n!=find(xrm,{0o005,0o065}) then exit end if
|
|
atom addr = peek4u(code_mem+pc+2)
|
|
pc += hxl(pc,{2,4},"%s [%s]",{op,get_var_name(addr)})
|
|
case 0o061:
|
|
case 0o071:
|
|
case 0o205:
|
|
integer n = find(opcode,{0o061,0o071,0o205})
|
|
string op = {"xor","cmp","test"}[n]
|
|
xrm = peek(code_mem+pc+1)
|
|
if and_bits(xrm,0o300)!=0o300 then exit end if
|
|
string r1 = regs[and_bits(xrm,0o070)/0o010+1]
|
|
string r2 = regs[and_bits(xrm,0o007)+1]
|
|
pc += hxl(pc,2,"%s %s,%s",{op,r1,r2})
|
|
case 0o017:
|
|
xrm = peek(code_mem+pc+1)
|
|
switch xrm do
|
|
case 0o224:
|
|
case 0o225:
|
|
case 0o234:
|
|
case 0o235:
|
|
case 0o236:
|
|
case 0o237:
|
|
string cc = cccodes[and_bits(xrm,0o017)+1]
|
|
xrm = peek(code_mem+pc+2)
|
|
if xrm=0o300 then
|
|
pc += hxl(pc,3,"set%s al",{cc})
|
|
elsif xrm=0o301 then
|
|
pc += hxl(pc,3,"set%s cl",{cc})
|
|
else
|
|
exit
|
|
end if
|
|
case 0o204:
|
|
integer offset = peek4s(code_mem+pc+2)
|
|
pc += hxl(pc,{2,4},"jz %d",{pc+6+offset+1})
|
|
else
|
|
exit
|
|
end switch
|
|
case 0o010:
|
|
case 0o040:
|
|
xrm = peek(code_mem+pc+1)
|
|
if xrm=0o310 then
|
|
string lop = {"or","and"}[find(opcode,{0o010,0o040})]
|
|
pc += hxl(pc,2,"%s al,cl",{lop})
|
|
else
|
|
exit
|
|
end if
|
|
case 0o120:
|
|
case 0o122:
|
|
case 0o130:
|
|
case 0o131:
|
|
case 0o132:
|
|
string op = {"push","pop"}[find(and_bits(opcode,0o070),{0o020,0o030})]
|
|
string reg = regs[and_bits(opcode,0o007)+1]
|
|
pc += hxl(pc,1,"%s %s",{op,reg})
|
|
case 0o231:
|
|
pc += hxl(pc,1,"cdq")
|
|
case 0o164:
|
|
case 0o353:
|
|
string jop = iff(opcode=0o164?"jz":"jmp")
|
|
integer offset = peek1s(code_mem+pc+1)
|
|
pc += hxl(pc,{1,1},"%s %d",{jop,pc+2+offset+1})
|
|
case 0o351:
|
|
integer offset = peek4s(code_mem+pc+1)
|
|
pc += hxl(pc,{1,4},"jmp %d",{pc+5+offset+1})
|
|
case 0o303:
|
|
pc += hxl(pc,1,"ret")
|
|
case 0o350:
|
|
integer offset = peek4s(code_mem+pc+1)
|
|
atom addr = offset+code_mem+pc+5
|
|
integer n = find(addr,builtins)
|
|
pc += hxl(pc,{1,4},"call :%s",{builtin_names[n]})
|
|
case 0o001:
|
|
case 0o041:
|
|
case 0o051:
|
|
integer n = find(opcode,{0o001,0o041,0o051})
|
|
string op = {"add","and","sub"}[n]
|
|
xrm = peek(code_mem+pc+1)
|
|
switch xrm do
|
|
case 0o004:
|
|
if peek(code_mem+pc+2)=0o044 then
|
|
pc += hxl(pc,3,"%s [esp],eax",{op})
|
|
else
|
|
exit
|
|
end if
|
|
else
|
|
exit
|
|
end switch
|
|
case 0o367:
|
|
xrm = peek(code_mem+pc+1)
|
|
if and_bits(xrm,0o300)!=0o300 then exit end if
|
|
integer n = find(and_bits(xrm,0o070),{0o030,0o040,0o070})
|
|
if n=0 then exit end if
|
|
string op = {"neg","mul","idiv"}[n]
|
|
string reg = regs[and_bits(xrm,0o007)+1]
|
|
pc += hxl(pc,2,"%s %s",{op,reg})
|
|
else
|
|
exit
|
|
end switch
|
|
end while
|
|
if pc<length(code) then
|
|
?"incomplete:"
|
|
if xrm=-1 then
|
|
?{pc+1,sprintf("0o%03o",opcode)}
|
|
else
|
|
?{pc+1,sprintf("0o%03o 0o%03o",{opcode,xrm})}
|
|
end if
|
|
end if
|
|
end procedure
|
|
|
|
procedure main(sequence cl)
|
|
open_files(cl)
|
|
toks = lex()
|
|
object t = parse()
|
|
code_gen(t)
|
|
fixup()
|
|
decode()
|
|
free({var_mem,code_mem})
|
|
close_files()
|
|
end procedure
|
|
|
|
--main(command_line())
|
|
main({0,0,"gcd.c"})
|