(notonline)--> -- -- 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"})