فهرست منبع

+ initial revision, it runs simple Alpha Linux ELF executables
- integer operations are nearly completed (non with overflow checking)
- floating point operations aren't implemented (except loading and
storing)
- only the really necessary system calls are implemented by dummys
write syscalls are redirected to the console

florian 26 سال پیش
والد
کامیت
d60550da2e
5فایلهای تغییر یافته به همراه2155 افزوده شده و 0 حذف شده
  1. 1278 0
      utils/simulator/alphasim.pas
  2. 211 0
      utils/simulator/fastmm64.pas
  3. 307 0
      utils/simulator/mm64.pas
  4. 122 0
      utils/simulator/simbase.pas
  5. 237 0
      utils/simulator/simlib.pas

+ 1278 - 0
utils/simulator/alphasim.pas

@@ -0,0 +1,1278 @@
+{
+    $Id$
+    This file is part of the Free Pascal simulator environment
+    Copyright (c) 1999 by Florian Klaempfl
+
+    This file is the main file of the DEC Alpha simulation
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+{$N+}
+{ $define DEBUG}
+program alphaemu;
+
+  uses
+     dos,simbase,simlib,
+{$ifdef FPC}
+{$ifdef go32v2}
+     dpmiexcp,
+{$endif go32v2}
+{$endif FPC}
+{$ifdef TP}
+     mm64
+{$else TP}
+     {$define fastmem}
+     fastmm64
+{$endif TP}
+     ;
+
+  { elf file types }
+  type
+     telf64_hdr = record
+        e_ident : array[0..15] of char;
+        e_type : integer;
+        e_machine : word;
+        version : longint;
+        e_entry : qword;
+        e_phoff : qword;
+        e_shoff : qword;
+        e_flags : longint;
+        e_ehsize : integer;
+        e_phentsize : integer;
+        e_phnum : integer;
+        e_shentsize : integer;
+        e_shnum : integer;
+        e_shstrndx : integer;
+     end;
+
+     telf64_phdr = record
+        p_type : longint;
+        p_flags : longint;
+        { Segment file offset }
+        p_offset : qword;
+        { Segment virtual address }
+        p_vaddr : qword;
+        { Segment physical address }
+        p_paddr : qword;
+        { Segment size in file }
+        p_filesz : qword;
+        { Segment size in memory }
+        p_memsz : qword;
+        { Segment alignment, file & memory }
+        p_align : qword;
+     end;
+
+     telf64_phdr_array = array[0..0] of telf64_phdr;
+     pelf64_phdr_array = ^telf64_phdr_array;
+
+  const
+     { 64kB Stacksize }
+     stacksize = 64.0*1024.0;
+     { stack start at 4 GB }
+     stackstart = 1024.0*1024.0*1024.0*4.0-stacksize;
+  { alpha specific types }
+  type
+     tintreg = record
+        case tindex of
+           1 : (all64 : qword);
+           2 : (valueq : int64);
+           3 : (low32 : dword;high32 : dword);
+           4 : (bytes : array[0..7] of byte)
+     end;
+
+     tfloatreg = record
+        case tindex of
+           1 : (valued : double);
+           2 : (valueq : qword);
+     end;
+
+     tinstruction = dword;
+
+     tintregs = array[0..31] of tintreg;
+     tfloatregs = array[0..31] of tfloatreg;
+
+     tstate = object
+        r : tintregs;
+        f : tfloatregs;
+        pc : taddr;
+        fpcr : qword;
+     end;
+
+  const
+     r_v0 = 0;
+     r_t0 = 1;
+
+     r_fp = 15;
+     r_a0 = 16;
+     r_a1 = 17;
+     r_a2 = 18;
+     r_a3 = 19;
+     r_a4 = 20;
+     r_a5 = 11;
+
+     r_ra = 26;
+     r_at = 28;
+     r_gp = 29;
+     r_sp = 30;
+     r_zero = 31;
+
+     f_zero = 31;
+
+  type
+     talphasim = object
+        state : tstate;
+        memory : tmemorymanager;
+        { number of executed instructions }
+        instrcount : qword;
+        { time when the emulation was started }
+        starttime : double;
+        { starts the execution at address pc }
+        procedure run(pc : taddr);
+        { gives a message about an illegal opcode }
+        { at the given address                    }
+        procedure illegalopcode(addr : taddr);
+        { dumps the contens of the register a0 to a[count] }
+        procedure dumparguments(count : tindex);
+        { dumps the contents of the function result register }
+        procedure dumpv0;
+        constructor init;
+        destructor done;
+     end;
+
+  var
+     sim : talphasim;
+
+  procedure dump_phdr(const h : telf64_phdr);
+
+    begin
+{$ifdef DEBUG}
+       writeln('  Type: $',hexstr(h.p_type,8));
+       writeln('  Flags: $',hexstr(h.p_flags,8));
+       writeln('  Segment file offset: $',qword2str(h.p_offset));
+       writeln('  Segment virtual address: $',qword2str(h.p_vaddr));
+       writeln('  Segment physical address: $',qword2str(h.p_paddr));
+       writeln('  Segment size in file: $',qword2str(h.p_filesz));
+       writeln('  Segment size in memory: $',qword2str(h.p_memsz));
+       writeln('  Segment alignment, file & memory: $',qword2str(h.p_align));
+{$endif DEBUG}
+    end;
+
+  procedure _stopsim;{$ifdef TP}far;{$endif TP}
+
+    var
+      elapsedtime : double;
+
+    begin
+{$ifdef DEBUG}
+       elapsedtime:=realtime-sim.starttime;
+       write('Executed ',sim.instrcount:0:0,' instructions in ',
+         elapsedtime:0:2,' sec');
+       if elapsedtime<>0.0 then
+         begin
+            writeln(',');
+            writeln('equals to ',sim.instrcount/(elapsedtime*1000000.0):0:4,' MIPS');
+         end
+       else
+         writeln;
+{$endif DEBUG}
+       halt(1);
+    end;
+
+  constructor talphasim.init;
+
+    begin
+       memory.init;
+       { setup dummy registers }
+       state.r[31].valueq:=0;
+       state.f[31].valued:=0.0;
+       memory.allocate(stackstart,stacksize);
+    end;
+
+  procedure talphasim.illegalopcode(addr : taddr);
+
+    var
+       instruction : tinstruction;
+
+    begin
+       instruction:=memory.readd(addr);
+       writeln('Illegal instruction $',hexstr(instruction,8),' at $',qword2str(addr));
+       writeln('Opcode is: $',hexstr((instruction and $fc000000) shr 26,2));
+       writeln('  Function would be: $',hexstr((instruction and $1fe0) shr 5,3));
+       writeln;
+       stopsim;
+    end;
+
+  procedure talphasim.dumparguments(count : tindex);
+
+    var
+       i : tindex;
+
+    begin
+       if count>6 then
+         begin
+            writeln('Illegal number of arguments to print');
+            halt(1);
+         end;
+{$ifdef DEBUG}
+       for i:=0 to count-1 do
+         writeln('  Register a',i,' = $',qword2str(state.r[r_a0+i].valueq));
+{$endif DEBUG}
+    end;
+
+  procedure talphasim.dumpv0;
+
+    var
+       i : tindex;
+
+    begin
+{$ifdef DEBUG}
+       writeln('  Register v0 = $',qword2str(state.r[r_v0].valueq));
+{$endif DEBUG}
+    end;
+
+  procedure talphasim.run(pc : qword);
+
+    var
+       instruction : tinstruction;
+       rega,regb,regc : tindex;
+       lit : byte;
+       va : tintreg;
+
+    function getbranchdisp : qword;
+
+      var
+         l : longint;
+
+      begin
+         l:=longint(instruction and $1fffff)*4;
+         { sign extend }
+         if (l and $100000)<>0 then
+           l:=l or $fff00000;
+         getbranchdisp:=l;
+      end;
+
+    procedure instructionignored(const s : string);
+
+      begin
+{$ifdef DEBUG}
+         writeln('Instruction "',s,'" at $',qword2str(instructionpc),' ignored');
+{$endif DEBUG}
+      end;
+
+    procedure syscallignored(const s : string);
+
+      begin
+{$ifdef DEBUG}
+         writeln('SYSCALL "',s,'" at $',qword2str(instructionpc),' ignored');
+{$endif DEBUG}
+      end;
+
+    procedure syscalldefault(const s : string);
+
+      begin
+{$ifdef DEBUG}
+         writeln('SYSCALL "',s,'" at $',qword2str(instructionpc),', default value returned');
+{$endif DEBUG}
+      end;
+
+    var
+       i : tindex;
+       fs : single;
+       ib : byte;
+       il : longint;
+       fc : comp;
+       ic : char;
+       valueqa,valueqb : qword;
+       oi : oword;
+       count : qword;
+{$ifdef FASTMEM}
+       block : pdword;
+       fastpc : longint;
+       updatepc : boolean;
+{$endif FASTMEM}
+
+    begin
+       instrcount:=0;
+       state.pc:=pc;
+       { setting up the stack pointer }
+       state.r[r_sp].valueq:=stackstart+stacksize-24;
+       { setting up command line parameters ... }
+       state.r[r_a0].valueq:=0;
+       state.r[r_a1].valueq:=0;
+       { ... and environment }
+       state.r[r_a2].valueq:=0;
+
+       starttime:=realtime;
+{$ifdef FASTMEM}
+       updatepc:=true;
+{$endif FASTMEM}
+       repeat
+         { read the next instruction }
+{$ifdef FASTMEM}
+         if updatepc then
+           begin
+              block:=pdword(memory.mem[((tqwordrec(state.pc).high32 and $f) shl 12) or
+                ((tqwordrec(state.pc).low32 and $fff) shr 20)]);
+              fastpc:=(tqwordrec(state.pc).low32 and $fffff) shr 2;
+           end;
+         instruction:=block[fastpc];
+         inc(fastpc);
+         updatepc:=fastpc>1024*256-1;
+{$else FASTMEM}
+         instruction:=memory.readalignedd(state.pc);
+{$endif FASTMEM}
+         instructionpc:=state.pc;
+         state.pc:=state.pc+4;
+
+         { decode the instruction }
+         case (instruction and $fc000000) shr 26 of
+            { CALL_PAL }
+            $0:
+              begin
+                 case instruction and $3ffffff of
+                    { halt }
+                    0:
+                       exit;
+                    131:
+                      begin
+                         if state.r[r_v0].high32=0 then
+                           case state.r[r_v0].low32 of
+                              { Setup }
+                              0:
+                                begin
+                                   syscallignored('setup');
+                                   { mimic proper execution }
+                                   state.r[r_v0].valueq:=0;
+                                end;
+                              1:
+                                begin
+                                   exit;
+                                end;
+                              4:
+                                begin
+                                   syscallignored('write');
+                                   state.r[r_v0].valueq:=0;
+                                   count:=0;
+                                   while count<state.r[r_a2].valueq do
+                                     begin
+                                        byte(ic):=memory.readb(state.r[r_a1].valueq+count);
+                                        { all output goes currently to stdout }
+                                        if ic=#10 then
+                                          writeln(output)
+                                        else
+                                          write(output,ic);
+
+                                        count:=count+1;
+                                        state.r[r_v0].valueq:=state.r[r_v0].valueq+1;
+                                     end;
+                                end;
+                              20:
+                                begin
+                                   syscalldefault('getpid');
+                                   { return a default value }
+                                   state.r[r_v0].valueq:=501;
+                                end;
+                              24:
+                                begin
+                                   syscalldefault('getuid');
+                                   { return a default value }
+                                   state.r[r_v0].valueq:=501;
+                                end;
+                              45:
+                                begin
+                                   syscallignored('brk');
+                                   { mimic proper execution }
+                                   state.r[r_v0].valueq:=0;
+                                end;
+                              { alpha specific }
+                              $100:
+                                begin
+                                   syscallignored('osf_getsysinfo');
+                                   { mimic proper execution }
+                                   state.r[r_v0].valueq:=0;
+                                end;
+                              $101:
+                                begin
+                                   syscallignored('osf_setsysinfo');
+                                   { mimic proper execution }
+                                   state.r[r_v0].valueq:=0;
+                                end;
+                              $144:
+                                begin
+                                   syscallignored('personality');
+                                   { mimic proper execution }
+                                   state.r[r_v0].valueq:=0;
+                                end;
+                              else
+                                begin
+                                   syscallignored('<Unknown>');
+                                   dumpv0;
+                                   dumparguments(4);
+                                end;
+
+                           end
+                         else
+                           begin
+                              syscallignored('<Unknown>');
+                              dumpv0;
+                              dumparguments(4);
+                           end;
+                      end;
+                    else
+                      writeln('PAL code $',hexstr(instruction and $3ffffff,8),' at $',
+                        qword2str(instructionpc),' ignored');
+                 end;
+              end;
+            { LDA }
+            $8:
+              begin
+                 rega:=(instruction and $3e00000) shr 21;
+                 regb:=(instruction and $1f0000) shr 16;
+                 if rega<>r_zero then
+                   state.r[rega].valueq:=state.r[regb].valueq+integer(instruction and $ffff);
+              end;
+            { LDAH }
+            $9:
+              begin
+                 rega:=(instruction and $3e00000) shr 21;
+                 regb:=(instruction and $1f0000) shr 16;
+                 if rega<>r_zero then
+                   state.r[rega].valueq:=state.r[regb].valueq+
+                     (longint(integer(instruction and $ffff))*65536);
+              end;
+            { LDQ_U }
+            $B:
+              begin
+                 { !!!!! no MSB support yet! }
+                 rega:=(instruction and $3e00000) shr 21;
+                 regb:=(instruction and $1f0000) shr 16;
+                 valueqb:=state.r[regb].valueq+
+                     (longint(integer(instruction and $ffff)));
+                 tqwordrec(valueqb).low32:=tqwordrec(valueqb).low32 and $fffffff8;
+                 if rega<>r_zero then
+                   state.r[rega].valueq:=memory.readq(valueqb);
+              end;
+            { STQ_U }
+            $f:
+              begin
+                 { !!!!! no MSB support yet! }
+                 rega:=(instruction and $3e00000) shr 21;
+                 regb:=(instruction and $1f0000) shr 16;
+                 va.valueq:=state.r[regb].valueq+
+                   (longint(integer(instruction and $ffff)));
+                 memory.writeq(va.valueq,state.r[rega].valueq);
+              end;
+
+            { ************* opcode $10 ************** }
+            $10:
+              begin
+                 rega:=(instruction and $3e00000) shr 21;
+                 regb:=(instruction and $1f0000) shr 16;
+                 regc:=instruction and $1f;
+                 valueqa:=state.r[rega].valueq;
+                 if (instruction and $1000)<>0 then
+                   valueqb:=(instruction and $1fe000) shr 13
+                 else
+                   valueqb:=state.r[regb].valueq;
+                 case (instruction and $fe0) shr 5 of
+                    { ADDL }
+                    $0:
+                      begin
+                         if regc<>r_zero then
+                           state.r[regc].low32:=tqwordrec(valueqa).low32+tqwordrec(valueqb).low32;
+                      end;
+                    { CMPULT }
+                    $1D:
+                      begin
+                         if (regc<>r_zero) then
+                           state.r[regc].valueq:=byte(ltu(valueqa,valueqb));
+                      end;
+                    { ADDQ }
+                    $20:
+                      begin
+                         if regc<>r_zero then
+                           state.r[regc].valueq:=valueqa+valueqb;
+                      end;
+                    { S4ADDQ }
+                    $22:
+                      begin
+                         if regc<>r_zero then
+                           state.r[regc].valueq:=valueqa*4+valueqb;
+                      end;
+                    { SUBQ }
+                    $29:
+                      begin
+                         if regc<>r_zero then
+                           state.r[regc].valueq:=valueqa-valueqb;
+                      end;
+                    { S4SUBQ }
+                    $2B:
+                      begin
+                         if regc<>r_zero then
+                           state.r[regc].valueq:=valueqa*4-valueqb;
+                      end;
+                    { CMPEQ }
+                    $2D:
+                      begin
+                         if (regc<>r_zero) then
+                           state.r[regc].valueq:=byte(valueqa=valueqb);
+                      end;
+                    { S8ADDQ }
+                    $32:
+                      begin
+                         if regc<>r_zero then
+                           state.r[regc].valueq:=valueqa*8+valueqb;
+                      end;
+                    { S8SUBQ }
+                    $3B:
+                      begin
+                         if regc<>r_zero then
+                           state.r[regc].valueq:=valueqa*8-valueqb;
+                      end;
+                    { CMPULE }
+                    $3D:
+                      begin
+                         if (regc<>r_zero) then
+                           state.r[regc].valueq:=byte(leu(valueqa,valueqb));
+                      end;
+                    { CMPLT }
+                    $4D:
+                      begin
+                         if (regc<>r_zero) then
+                           state.r[regc].valueq:=byte(valueqa<valueqb);
+                      end;
+                    { CMPLE }
+                    $6D:
+                      begin
+                         if (regc<>r_zero) then
+                           state.r[regc].valueq:=byte(valueqa<=valueqb);
+                      end;
+                    else
+                      illegalopcode(instructionpc);
+                 end;
+              end;
+
+            { ************* opcode $11 ************** }
+            $11:
+              begin
+                 rega:=(instruction and $3e00000) shr 21;
+                 regb:=(instruction and $1f0000) shr 16;
+                 regc:=instruction and $1f;
+                 valueqa:=state.r[rega].valueq;
+                 if (instruction and $1000)<>0 then
+                   valueqb:=(instruction and $1fe000) shr 13
+                 else
+                   valueqb:=state.r[regb].valueq;
+                 case (instruction and $fe0) shr 5 of
+                    { AND }
+                    $00:
+                      begin
+                         if regc<>r_zero then
+                           begin
+                              state.r[regc].low32:=tqwordrec(valueqa).low32 and
+                                tqwordrec(valueqb).low32;
+                              state.r[regc].high32:=tqwordrec(valueqa).high32 and
+                                tqwordrec(valueqb).high32;
+                           end;
+                      end;
+                    { BIC }
+                    $08:
+                      begin
+                         if regc<>r_zero then
+                           begin
+                              state.r[regc].low32:=tqwordrec(valueqa).low32 and
+                                not(tqwordrec(valueqb).low32);
+                              state.r[regc].high32:=tqwordrec(valueqa).high32 and
+                                not(tqwordrec(valueqb).high32);
+                           end;
+                      end;
+                    { CMOVLBS }
+                    $14:
+                      begin
+                         if (regc<>r_zero) and ((tqwordrec(valueqa).low32 and 1)<>0) then
+                           state.r[regc].valueq:=valueqb;
+                      end;
+                    { CMOVLBC }
+                    $16:
+                      begin
+                         if (regc<>r_zero) and ((tqwordrec(valueqa).low32 and 1)=0) then
+                           state.r[regc].valueq:=valueqb;
+                      end;
+                    { BIS }
+                    $20:
+                      begin
+                         if regc<>r_zero then
+                           begin
+                              state.r[regc].low32:=tqwordrec(valueqa).low32 or
+                                tqwordrec(valueqb).low32;
+                              state.r[regc].high32:=tqwordrec(valueqa).high32 or
+                                tqwordrec(valueqb).high32;
+                           end;
+                      end;
+                    { CMOVEQ }
+                    $24:
+                      begin
+                         if (regc<>r_zero) and (valueqa=0) then
+                           state.r[regc].valueq:=valueqb;
+                      end;
+                    { CMOVNE }
+                    $26:
+                      begin
+                         if (regc<>r_zero) and (valueqa<>0) then
+                           state.r[regc].valueq:=valueqb;
+                      end;
+                    { ORNOT }
+                    $28:
+                      begin
+                         if regc<>r_zero then
+                           begin
+                              state.r[regc].low32:=tqwordrec(valueqa).low32 or
+                                not(tqwordrec(valueqb).low32);
+                              state.r[regc].high32:=tqwordrec(valueqa).high32 or
+                                not(tqwordrec(valueqb).high32);
+                           end;
+                      end;
+                    { XOR }
+                    $40:
+                      begin
+                         if regc<>r_zero then
+                           begin
+                              state.r[regc].low32:=state.r[rega].low32 xor
+                                tqwordrec(valueqb).low32;
+                              state.r[regc].high32:=state.r[rega].high32 xor
+                                tqwordrec(valueqb).high32;
+                           end;
+                      end;
+                    { CMOVLT }
+                    $44:
+                      begin
+                         if (regc<>r_zero) and (valueqa<0) then
+                           state.r[regc].valueq:=valueqb;
+                      end;
+                    { CMOVGE }
+                    $46:
+                      begin
+                         if (regc<>r_zero) and (valueqa>=0) then
+                           state.r[regc].valueq:=valueqb;
+                      end;
+                    { EQV }
+                    $48:
+                      begin
+                         if regc<>r_zero then
+                           begin
+                              state.r[regc].low32:=tqwordrec(valueqa).low32 xor
+                                not(tqwordrec(valueqb).low32);
+                              state.r[regc].high32:=tqwordrec(valueqa).high32 xor
+                                not(tqwordrec(valueqb).high32);
+                           end;
+                      end;
+                    { CMOVLE }
+                    $64:
+                      begin
+                         if (regc<>r_zero) and (valueqa<=0) then
+                           state.r[regc].valueq:=valueqb;
+                      end;
+                    { CMOVGT }
+                    $66:
+                      begin
+                         if (regc<>r_zero) and (valueqa<=0) then
+                           state.r[regc].valueq:=valueqb;
+                      end;
+                    else
+                      illegalopcode(instructionpc);
+                 end;
+              end;
+
+            { ************* opcode $12 ************** }
+            $12:
+              begin
+                 rega:=(instruction and $3e00000) shr 21;
+                 regb:=(instruction and $1f0000) shr 16;
+                 regc:=instruction and $1f;
+                 valueqa:=state.r[rega].valueq;
+                 if (instruction and $1000)<>0 then
+                   valueqb:=(instruction and $1fe000) shr 13
+                 else
+                   valueqb:=state.r[regb].valueq;
+                 case (instruction and $fe0) shr 5 of
+                    { MSKBL }
+                    $02:
+                      begin
+                         { !!!!! no MSB support yet! }
+                         il:=1 shl (tqwordrec(valueqb).low32 and $7);
+                         if (regc<>r_zero) then
+                           byte_zap(valueqa,il and $ff,state.r[regc].valueq);
+                      end;
+                    { EXTBL }
+                    $06:
+                      begin
+                         { !!!!! no MSB support yet! }
+                         shift_right_q(valueqa,(tqwordrec(valueqb).low32 and $7)*8,valueqa);
+                         if (regc<>r_zero) then
+                           byte_zap(valueqa,$fe,state.r[regc].valueq);
+                      end;
+                    { INSBL }
+                    $0B:
+                      begin
+                         { !!!!! no MSB support yet! }
+                         il:=1 shl (tqwordrec(valueqb).low32 and $7);
+                         shift_left_q(valueqa,(tqwordrec(valueqb).low32 and $7)*8,valueqa);
+                         if (regc<>r_zero) then
+                           byte_zap(valueqa,not(il and $ff),state.r[regc].valueq);
+                      end;
+                    { MSKWL }
+                    $12:
+                      begin
+                         { !!!!! no MSB support yet! }
+                         il:=3 shl (tqwordrec(valueqb).low32 and $7);
+                         if (regc<>r_zero) then
+                           byte_zap(valueqa,il and $ff,state.r[regc].valueq);
+                      end;
+                    { EXTWL }
+                    $16:
+                      begin
+                         { !!!!! no MSB support yet! }
+                         shift_right_q(valueqa,(tqwordrec(valueqb).low32 and $7)*8,valueqa);
+                         if (regc<>r_zero) then
+                           byte_zap(valueqa,$fc,state.r[regc].valueq);
+                      end;
+                    { MSKLL }
+                    $22:
+                      begin
+                         { !!!!! no MSB support yet! }
+                         il:=$f shl (tqwordrec(valueqb).low32 and $7);
+                         if (regc<>r_zero) then
+                           byte_zap(valueqa,il and $ff,state.r[regc].valueq);
+                      end;
+                    { EXTLL }
+                    $26:
+                      begin
+                         { !!!!! no MSB support yet! }
+                         shift_right_q(valueqa,(tqwordrec(valueqb).low32 and $7)*8,valueqa);
+                         if (regc<>r_zero) then
+                           byte_zap(valueqa,$f0,state.r[regc].valueq);
+                      end;
+                    { ZAP }
+                    $30:
+                      begin
+                         if regc<>r_zero then
+                           byte_zap(valueqa,trunc(valueqb),state.r[regc].valueq);
+                      end;
+                    { ZAPNOT }
+                    $31:
+                      begin
+                         if regc<>r_zero then
+                           byte_zap(valueqa,not(trunc(valueqb)),state.r[regc].valueq);
+                      end;
+                    { MSKQL }
+                    $32:
+                      begin
+                         { !!!!! no MSB support yet! }
+                         il:=$ff shl (tqwordrec(valueqb).low32 and $7);
+                         if (regc<>r_zero) then
+                           byte_zap(valueqa,il and $ff,state.r[regc].valueq);
+                      end;
+                    { SRL }
+                    $34:
+                      begin
+                         if regc<>r_zero then
+                           shift_right_q(valueqa,trunc(valueqb) and $3f,state.r[regc].valueq);
+                      end;
+                    { EXTQL }
+                    $36:
+                      begin
+                         { !!!!! no MSB support yet! }
+                         shift_right_q(valueqa,(tqwordrec(valueqb).low32 and $7)*8,valueqa);
+                         if (regc<>r_zero) then
+                           state.r[regc].valueq:=valueqa;
+                      end;
+                    { SLL }
+                    $39:
+                      begin
+                         if regc<>r_zero then
+                           shift_left_q(valueqa,trunc(valueqb) and $3f,state.r[regc].valueq);
+                      end
+                    else
+                      illegalopcode(instructionpc);
+                 end;
+              end;
+
+            { ************* opcode $13 ************** }
+            $13:
+              begin
+                 rega:=(instruction and $3e00000) shr 21;
+                 regb:=(instruction and $1f0000) shr 16;
+                 regc:=instruction and $1f;
+                 valueqa:=state.r[rega].valueq;
+                 if (instruction and $1000)<>0 then
+                   valueqb:=(instruction and $1fe000) shr 13
+                 else
+                   valueqb:=state.r[regb].valueq;
+                 case (instruction and $fe0) shr 5 of
+                    { UMULH }
+                    $30:
+                      if regc<>31 then
+                        begin
+                           mulqword(valueqa,valueqb,oi);
+                           state.r[regc].valueq:=towordrec(oi).high64;
+                        end;
+                    else
+                      illegalopcode(instructionpc);
+                 end;
+              end;
+
+            { ************* opcode $17 ************** }
+            $17:
+              case (instruction and $ffe0) shr 5 of
+                 { MT_FPCR }
+                 $24:
+                   begin
+                      rega:=(instruction and $3e00000) shr 21;
+                      state.fpcr:=state.f[rega].valueq;
+                   end;
+                 { MF_FPCR }
+                 $25:
+                   begin
+                      rega:=(instruction and $3e00000) shr 21;
+                      if rega<>f_zero then
+                        state.f[rega].valueq:=state.fpcr;
+                   end;
+                 else
+                   illegalopcode(instructionpc);
+              end;
+
+            { ************* opcode $18 ************** }
+            $18:
+              case instruction and $ffff of
+                 { EXCB }
+                 $400:
+                    instructionignored('EXCN');
+                 else
+                    illegalopcode(instructionpc);
+              end;
+
+            { JMP,JSR,RET JSR_COROUTINE }
+            $1a:
+              begin
+                 rega:=(instruction and $3e00000) shr 21;
+                 regb:=(instruction and $1f0000) shr 16;
+                 va:=state.r[regb];
+                 va.low32:=va.low32 and $fffffffe;
+                 if rega<>31 then
+                   state.r[rega].valueq:=state.pc;
+                 state.pc:=va.valueq;
+{$ifdef FASTMEM}
+                 updatepc:=true;
+{$endif FASTMEM}
+              end;
+            { LDS }
+            $22:
+              begin
+                 { !!!!! no MSB support yet! }
+                 rega:=(instruction and $3e00000) shr 21;
+                 regb:=(instruction and $1f0000) shr 16;
+                 va.valueq:=state.r[regb].valueq+
+                   (longint(integer(instruction and $ffff)));
+                 if rega<>f_zero then
+                   begin
+                      { we need to copy the bit pattern! }
+                      dword(fs):=memory.readd(va.valueq);
+                      state.f[rega].valued:=fs;
+                   end;
+                 { !!!!!! no translation exceptions! }
+              end;
+            { LDT }
+            $23:
+              begin
+                 { !!!!! no MSB support yet! }
+                 rega:=(instruction and $3e00000) shr 21;
+                 regb:=(instruction and $1f0000) shr 16;
+                 va.valueq:=state.r[regb].valueq+
+                   (longint(integer(instruction and $ffff)));
+                 if rega<>f_zero then
+                   state.f[rega].valueq:=memory.readq(va.valueq);
+                 { !!!!!! no translation exceptions! }
+              end;
+{$ifdef dummy}
+            { !!!!!!!! STF }
+            $24:
+              begin
+                 { !!!!! no MSB support yet! }
+                 rega:=(instruction and $3e00000) shr 21;
+                 regb:=(instruction and $1f0000) shr 16;
+                 va.valueq:=state.r[regb].valueq+
+                   (longint(integer(instruction and $ffff)));
+                 fs:=state.f[rega].valued;
+                 memory.writed(va.valueq,longint(fs));
+                 { !!!!!! no tranlation exceptions! }
+              end;
+            { !!!!!!!!!!!! STG }
+            $25:
+              begin
+                 { !!!!! no MSB support yet! }
+                 rega:=(instruction and $3e00000) shr 21;
+                 regb:=(instruction and $1f0000) shr 16;
+                 va.valueq:=state.r[regb].valueq+
+                   (longint(integer(instruction and $ffff)));
+                 memory.writeq(va.valueq,state.f[rega].valueq);
+                 { !!!!!! no translation exceptions! }
+              end;
+{$endif dummy}
+            { !!!!!!!!!!!!! STS }
+            $26:
+              begin
+                 { !!!!! no MSB support yet! }
+                 rega:=(instruction and $3e00000) shr 21;
+                 regb:=(instruction and $1f0000) shr 16;
+                 va.valueq:=state.r[regb].valueq+
+                   (longint(integer(instruction and $ffff)));
+                 fs:=state.f[rega].valued;
+                 memory.writed(va.valueq,longint(fs));
+                 { !!!!!! no tranlation exceptions! }
+              end;
+            { STT }
+            $27:
+              begin
+                 { !!!!! no MSB support yet! }
+                 rega:=(instruction and $3e00000) shr 21;
+                 regb:=(instruction and $1f0000) shr 16;
+                 va.valueq:=state.r[regb].valueq+
+                   (longint(integer(instruction and $ffff)));
+                 memory.writeq(va.valueq,state.f[rega].valueq);
+                 { !!!!!! no translation exceptions! }
+              end;
+            { LDL }
+            $28:
+              begin
+                 { !!!!! no MSB support yet! }
+                 rega:=(instruction and $3e00000) shr 21;
+                 regb:=(instruction and $1f0000) shr 16;
+                 if rega<>r_zero then
+                   state.r[rega].low32:=memory.readalignedd(state.r[regb].valueq+
+                     (longint(integer(instruction and $ffff))));
+                 { sign extend }
+                 if state.r[rega].low32<0 then
+                   state.r[rega].high32:=$ffffffff
+                 else
+                   state.r[rega].high32:=0;
+              end;
+            { LDQ }
+            $29:
+              begin
+                 { !!!!! no MSB support yet! }
+                 rega:=(instruction and $3e00000) shr 21;
+                 regb:=(instruction and $1f0000) shr 16;
+                 if rega<>r_zero then
+                   state.r[rega].valueq:=memory.readalignedq(state.r[regb].valueq+
+                     (longint(integer(instruction and $ffff))));
+              end;
+            { STL }
+            $2C:
+              begin
+                 { !!!!! no MSB support yet! }
+                 rega:=(instruction and $3e00000) shr 21;
+                 regb:=(instruction and $1f0000) shr 16;
+                 va.valueq:=state.r[regb].valueq+
+                   (longint(integer(instruction and $ffff)));
+                 memory.writealignedd(va.valueq,state.r[rega].low32);
+              end;
+            { STQ }
+            $2D:
+              begin
+                 { !!!!! no MSB support yet! }
+                 rega:=(instruction and $3e00000) shr 21;
+                 regb:=(instruction and $1f0000) shr 16;
+                 va.valueq:=state.r[regb].valueq+
+                   (longint(integer(instruction and $ffff)));
+                 memory.writeq(va.valueq,state.r[rega].valueq);
+              end;
+            { BR,BSR }
+            $30,$34:
+              begin
+                 rega:=(instruction and $3e00000) shr 21;
+                 if rega<>31 then
+                   state.r[rega].valueq:=state.pc;
+                 state.pc:=state.pc+getbranchdisp;
+{$ifdef FASTMEM}
+                 updatepc:=true;
+{$endif FASTMEM}
+              end;
+            { BLSC }
+            $38:
+              begin
+                 rega:=(instruction and $3e00000) shr 21;
+                 va.valueq:=state.pc+getbranchdisp;
+                 if (state.r[rega].low32 and 1)=0 then
+                   begin
+                      state.pc:=va.valueq;
+{$ifdef FASTMEM}
+                      updatepc:=true;
+{$endif FASTMEM}
+                   end;
+              end;
+            { BEQ }
+            $39:
+              begin
+                 rega:=(instruction and $3e00000) shr 21;
+                 va.valueq:=state.pc+getbranchdisp;
+                 if state.r[rega].valueq=0 then
+                   begin
+                      state.pc:=va.valueq;
+{$ifdef FASTMEM}
+                      updatepc:=true;
+{$endif FASTMEM}
+                   end;
+              end;
+            { BLT }
+            $3A:
+              begin
+                 rega:=(instruction and $3e00000) shr 21;
+                 va.valueq:=state.pc+getbranchdisp;
+                 if state.r[rega].valueq<0 then
+                   begin
+                      state.pc:=va.valueq;
+{$ifdef FASTMEM}
+                      updatepc:=true;
+{$endif FASTMEM}
+                   end;
+              end;
+            { BLE }
+            $3B:
+              begin
+                 rega:=(instruction and $3e00000) shr 21;
+                 va.valueq:=state.pc+getbranchdisp;
+                 if state.r[rega].valueq<=0 then
+                   begin
+                      state.pc:=va.valueq;
+{$ifdef FASTMEM}
+                      updatepc:=true;
+{$endif FASTMEM}
+                   end;
+              end;
+            { BLBS }
+            $3C:
+              begin
+                 rega:=(instruction and $3e00000) shr 21;
+                 va.valueq:=state.pc+getbranchdisp;
+                 if (state.r[rega].low32 and 1)<>0 then
+                   begin
+                      state.pc:=va.valueq;
+{$ifdef FASTMEM}
+                      updatepc:=true;
+{$endif FASTMEM}
+                   end;
+              end;
+            { BNE }
+            $3D:
+              begin
+                 rega:=(instruction and $3e00000) shr 21;
+                 va.valueq:=state.pc+getbranchdisp;
+                 if state.r[rega].valueq<>0 then
+                   begin
+                      state.pc:=va.valueq;
+{$ifdef FASTMEM}
+                      updatepc:=true;
+{$endif FASTMEM}
+                   end;
+              end;
+            { BGE }
+            $3E:
+              begin
+                 rega:=(instruction and $3e00000) shr 21;
+                 va.valueq:=state.pc+getbranchdisp;
+                 if state.r[rega].valueq>=0 then
+                   begin
+                      state.pc:=va.valueq;
+{$ifdef FASTMEM}
+                      updatepc:=true;
+{$endif FASTMEM}
+                   end;
+              end;
+            { BGT }
+            $3F:
+              begin
+                 rega:=(instruction and $3e00000) shr 21;
+                 va.valueq:=state.pc+getbranchdisp;
+                 if state.r[rega].valueq>0 then
+                   begin
+                      state.pc:=va.valueq;
+{$ifdef FASTMEM}
+                      updatepc:=true;
+{$endif FASTMEM}
+                   end;
+              end;
+          else
+              illegalopcode(instructionpc);
+         end;
+         instrcount:=instrcount+1;
+       until false;
+    end;
+
+  destructor talphasim.done;
+
+    begin
+       { deallocate memory }
+       { memory.done; }
+    end;
+
+  procedure illelfformat;
+
+    begin
+       writeln('Illegal format of ELF');
+       halt(1);
+    end;
+
+  var
+     f : file;
+     elf64_hdr : telf64_hdr;
+     i : tindex;
+     j,q : qword;
+     b : byte;
+     elf64_phdr : pelf64_phdr_array;
+
+  const
+     et2str : array[0..6] of string[10] = ('ET_NONE','ET_REL','ET_EXEC',
+                                           'ET_DYN','ET_CORE','ET_LOPROC',
+                                           'ET_HIPROC');
+     em2str : array[0..11] of string[10] = ('EM_NONE','EM_M32','EM_SPARC',
+                                            'EM_386','EM_68K','EM_88K',
+                                            'EM_486','EM_860','EM_MIPS','',
+                                            'EM_MIPS_RS4_BE','EM_SPARC64');
+
+  begin
+     if paramcount<>1 then
+       begin
+          writeln('Usage ALPHAEMU <elf-executable>');
+          halt(1);
+       end;
+{$ifdef DEBUG}
+     write('Init... ');
+{$endif DEBUG}
+     assign(f,paramstr(1));
+     {$I-}
+     reset(f,1);
+     {$I+}
+     if ioresult<>0 then
+       begin
+          writeln;
+          writeln('Can''t open input file ',paramstr(1));
+          halt(1);
+       end;
+     blockread(f,elf64_hdr,sizeof(elf64_hdr));
+{$ifdef DEBUG}
+     writeln('Signature:');
+     for i:=0 to 15 do
+       write(elf64_hdr.e_ident[i],'(',ord(elf64_hdr.e_ident[i]),') ');
+     writeln;
+     writeln('ELF type: ',et2str[elf64_hdr.e_type]);
+     case elf64_hdr.e_machine of
+        0..11:
+          writeln('ELF machine: ',em2str[elf64_hdr.e_machine]);
+        15:
+          writeln('ELF machine: EM_PARISC');
+        18:
+          writeln('ELF machine: EM_SPARC32PLUS');
+        20:
+          writeln('ELF machine: EM_PPC');
+        $9026:
+          writeln('ELF machine: EM_ALPHA');
+        else
+          illelfformat;
+     end;
+
+     writeln('ELF header size: $',hexstr(elf64_hdr.e_ehsize,8));
+     writeln('Entry point: $',qword2str(elf64_hdr.e_entry));
+
+     writeln('Program header table file offset: $',qword2str(elf64_hdr.e_phoff));
+     writeln('Number of program headers : $',hexstr(elf64_hdr.e_phnum,8));
+     writeln('Size of one program header: $',hexstr(elf64_hdr.e_phentsize,8));
+
+     writeln('Section header table file offset: $',qword2str(elf64_hdr.e_shoff));
+     { writeln('Section name index: $',hexstr(elf64_hdr.e_shstrndx,8)); }
+{$endif}
+     if (elf64_hdr.e_ident[0]<>chr(127)) or
+       (elf64_hdr.e_ident[1]<>'E') or
+       (elf64_hdr.e_ident[2]<>'L') or
+       (elf64_hdr.e_ident[3]<>'F') or
+       (elf64_hdr.e_type<>2) or
+       (elf64_hdr.e_machine<>$9026) then
+       illelfformat;
+
+     { load programm headers }
+     getmem(elf64_phdr,elf64_hdr.e_phentsize*elf64_hdr.e_phnum);
+     seek(f,trunc(elf64_hdr.e_phoff));
+     blockread(f,elf64_phdr^,elf64_hdr.e_phentsize*elf64_hdr.e_phnum);
+     for i:=0 to elf64_hdr.e_phnum-1 do
+       begin
+{$ifdef DEBUG}
+          writeln('Programm header ',i);
+          dump_phdr(elf64_phdr^[i]);
+{$endif DEBUG}
+       end;
+     { ok, now init the emulator }
+     sim.init;
+     {$ifdef FPC}
+     stopsim:=@_stopsim;
+     {$else FPC}
+     stopsim:=_stopsim;
+     {$endif FPC}
+{$ifdef DEBUG}
+     writeln('OK');
+     write('Loading memory... ');
+{$endif DEBUG}
+     { load memory }
+     for i:=0 to elf64_hdr.e_phnum-1 do
+       begin
+{$ifdef DEBUG}
+          write(i+1,' ');
+{$endif DEBUG}
+          sim.memory.allocate(elf64_phdr^[i].p_vaddr,elf64_phdr^[i].p_memsz);
+          seek(f,trunc(elf64_phdr^[i].p_offset));
+          j:=0;
+          { can we speedup the loading? }
+          if (tqwordrec(elf64_phdr^[i].p_filesz).low32 and $7)=0 then
+            while j<elf64_phdr^[i].p_filesz do
+              begin
+                 blockread(f,q,8);
+                 sim.memory.writeq(j+elf64_phdr^[i].p_vaddr,q);
+                 j:=j+8;
+              end
+          else
+            while j<elf64_phdr^[i].p_filesz do
+              begin
+                 blockread(f,b,1);
+                 sim.memory.writeb(j+elf64_phdr^[i].p_vaddr,b);
+                 j:=j+1;
+              end;
+       end;
+     { clean up from the file loading }
+     freemem(elf64_phdr,elf64_hdr.e_phentsize*elf64_hdr.e_phnum);
+     close(f);
+{$ifdef DEBUG}
+     writeln('OK');
+     writeln('Running program ...');
+{$endif DEBUG}
+     sim.run(elf64_hdr.e_entry);
+{$ifdef DEBUG}
+     writeln('Ready');
+{$endif DEBUG}
+     stopsim;
+     sim.done;
+  end.
+{
+  $Log$
+  Revision 1.1  1999-06-14 11:49:48  florian
+    + initial revision, it runs simple Alpha Linux ELF executables
+       - integer operations are nearly completed (non with overflow checking)
+       - floating point operations aren't implemented (except loading and
+         storing)
+       - only the really necessary system calls are implemented by dummys
+         write syscalls are redirected to the console
+
+}

+ 211 - 0
utils/simulator/fastmm64.pas

@@ -0,0 +1,211 @@
+{
+    $Id$
+    This file is part of the Free Pascal simulator environment
+    Copyright (c) 1999 by Florian Klaempfl
+
+    This unit implemements a memory manager for 64 bit processor
+    simulations, it needs a 32 bit compiler to be compiled
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+{$N+}
+unit fastmm64;
+
+  interface
+
+    uses
+       simbase;
+
+    type
+       taddr = qword;
+
+       tmemorymanager = object
+          mem : array[0..65535] of pbyte;
+          constructor init;
+          { "memory" access routines }
+          function readalignedq(addr : taddr) : qword;
+          function readq(addr : taddr) : qword;
+          function readalignedd(addr : taddr) : dword;
+          function readd(addr : taddr) : dword;
+          function readb(addr : taddr) : dword;
+          procedure writeb(addr : taddr;b : byte);
+          procedure writealignedd(addr : taddr;d : dword);
+          procedure writed(addr : taddr;d : dword);
+          procedure writeq(addr : taddr;q : qword);
+          procedure allocate(addr : taddr;size : qword);
+       end;
+
+    var
+       { address of the currently executed instruction, }
+       { necessary for correct output of exception      }
+       instructionpc : taddr;
+
+  implementation
+
+    procedure exception(const s : string;addr : taddr);
+
+      begin
+         writeln;
+         writeln('Exception: ',s,' at $',qword2str(addr));
+         stopsim;
+      end;
+
+    constructor tmemorymanager.init;
+
+      begin
+         fillchar(mem,sizeof(mem),0);
+      end;
+
+    procedure tmemorymanager.allocate(addr : taddr;size : qword);
+
+      procedure allocateblock(addr : taddr);
+
+        var
+           upperbits : longint;
+
+        begin
+           if (tqwordrec(addr).high32 and $fffffff0)<>0 then
+             begin
+                writeln('This memory manager supports only 36 bit');
+                halt(1);
+             end;
+           upperbits:=((tqwordrec(addr).high32 and $f) shl 12) or ((tqwordrec(addr).low32 and $fff) shr 20);
+           if not(assigned(mem[upperbits])) then
+             begin
+                getmem(mem[upperbits],1024*1024);
+                fillchar(mem[upperbits]^,1024*1024,0);
+             end;
+        end;
+
+      var
+         asize : qword;
+
+      begin
+         while size>0 do
+           begin
+              if size>1024*1024 then
+                asize:=1024*1024;
+              size:=size-asize;
+              allocateblock(addr);
+              addr:=addr+asize;
+           end;
+      end;
+
+    function tmemorymanager.readq(addr : taddr) : qword;
+
+      var
+         h : qword;
+
+      begin
+         tqwordrec(h).low32:=readd(addr);
+         tqwordrec(h).high32:=readd(addr+4);
+         readq:=h;
+      end;
+
+    function tmemorymanager.readd(addr : taddr) : dword;
+
+      begin
+         readd:=readb(addr)+readb(addr+1) shl 8+readb(addr+2) shl 16+
+           readb(addr+3) shl 24;
+      end;
+
+    function tmemorymanager.readalignedd(addr : taddr) : dword;
+
+      var
+         upperbits : longint;
+
+      begin
+         if (tqwordrec(addr).low32 and $3)<>0 then
+           exception('Alignment violation (dword) to $'+qword2str(addr),instructionpc);
+         upperbits:=((tqwordrec(addr).high32 and $f) shl 12) or ((tqwordrec(addr).low32 and $fff) shr 20);
+         if not(assigned(mem[upperbits])) then
+           exception('Access violation to $'+qword2str(addr),instructionpc);
+         readalignedd:=pdword(mem[upperbits])[(tqwordrec(addr).low32 and $fffff) shr 2];
+      end;
+
+    function tmemorymanager.readalignedq(addr : taddr) : qword;
+
+      var
+         upperbits : longint;
+
+      begin
+         if (tqwordrec(addr).low32 and $7)<>0 then
+           exception('Alignment violation (dword) to $'+qword2str(addr),instructionpc);
+         upperbits:=((tqwordrec(addr).high32 and $f) shl 12) or ((tqwordrec(addr).low32 and $fff) shr 20);
+         if not(assigned(mem[upperbits])) then
+           exception('Access violation to $'+qword2str(addr),instructionpc);
+         readalignedq:=pqword(mem[upperbits])[(tqwordrec(addr).low32 and $fffff) shr 3];
+      end;
+
+    function tmemorymanager.readb(addr : taddr) : dword;
+
+      var
+         upperbits : longint;
+
+      begin
+         upperbits:=((tqwordrec(addr).high32 and $f) shl 12) or ((tqwordrec(addr).low32 and $fff) shr 20);
+         if not(assigned(mem[upperbits])) then
+           exception('Access violation to $'+qword2str(addr),instructionpc);
+         readb:=mem[upperbits,tqwordrec(addr).low32 and $fffff];
+      end;
+
+    procedure tmemorymanager.writeb(addr : taddr;b : byte);
+
+      var
+         upperbits : longint;
+
+      begin
+         upperbits:=((tqwordrec(addr).high32 and $f) shl 12) or ((tqwordrec(addr).low32 and $fff) shr 20);
+         if not(assigned(mem[upperbits])) then
+           exception('Access violation to $'+qword2str(addr),instructionpc);
+         mem[upperbits,tqwordrec(addr).low32 and $fffff]:=b;
+      end;
+
+    procedure tmemorymanager.writealignedd(addr : taddr;d : dword);
+
+      var
+         upperbits : longint;
+
+      begin
+         if (tqwordrec(addr).low32 and $3)<>0 then
+           exception('Alignment violation (dword) to $'+qword2str(addr),instructionpc);
+         upperbits:=((tqwordrec(addr).high32 and $f) shl 12) or ((tqwordrec(addr).low32 and $fff) shr 20);
+         if not(assigned(mem[upperbits])) then
+           exception('Access violation to $'+qword2str(addr),instructionpc);
+         pdword(mem[upperbits])[(tqwordrec(addr).low32 and $fffff) shr 2]:=d;
+      end;
+
+    procedure tmemorymanager.writed(addr : taddr;d : dword);
+
+      begin
+         writeb(addr,tdword(d)[0]);
+         writeb(addr+1,tdword(d)[1]);
+         writeb(addr+2,tdword(d)[2]);
+         writeb(addr+3,tdword(d)[3]);
+      end;
+
+    procedure tmemorymanager.writeq(addr : taddr;q : qword);
+
+      begin
+         writed(addr,tqwordrec(q).low32);
+         writed(addr+4,tqwordrec(q).high32);
+      end;
+
+end.
+{
+  $Log$
+  Revision 1.1  1999-06-14 11:49:48  florian
+    + initial revision, it runs simple Alpha Linux ELF executables
+       - integer operations are nearly completed (non with overflow checking)
+       - floating point operations aren't implemented (except loading and
+         storing)
+       - only the really necessary system calls are implemented by dummys
+         write syscalls are redirected to the console
+
+}

+ 307 - 0
utils/simulator/mm64.pas

@@ -0,0 +1,307 @@
+{
+    $Id$
+    This file is part of the Free Pascal simulator environment
+    Copyright (c) 1999 by Florian Klaempfl
+
+    This unit implemements a memory manager for 64 bit processor
+    simulations, it works also with TP
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+{ a simple 64 bit simulator memory manager, also running with TP }
+{$N+}
+unit mm64;
+
+  interface
+
+    uses
+       simbase;
+
+    const
+       memoryblocksize = 32768;
+
+    type
+       taddr = qword;
+       tmemoryblock = array[0..memoryblocksize-1] of byte;
+       pmemoryblock = ^tmemoryblock;
+
+       pmemoryarea = ^tmemoryarea;
+       tmemoryarea = record
+         addr : qword;
+         memory : pmemoryblock;
+         size : dword;
+         next : pmemoryarea;
+       end;
+
+       tmemorymanager = object
+          mem : pmemoryarea;
+          constructor init;
+          { "memory" access routines }
+          function readalignedq(addr : taddr) : qword;
+          function readq(addr : taddr) : qword;
+          function readalignedd(addr : taddr) : dword;
+          function readd(addr : taddr) : dword;
+          function readb(addr : taddr) : dword;
+          procedure writeb(addr : taddr;b : byte);
+          procedure writealignedd(addr : taddr;d : dword);
+          procedure writed(addr : taddr;d : dword);
+          procedure writeq(addr : taddr;q : qword);
+          procedure allocate(addr : taddr;size : qword);
+       end;
+
+    var
+       { address of the currently executed instruction, }
+       { necessary for correct output of exception      }
+       instructionpc : taddr;
+
+  implementation
+
+    procedure exception(const s : string;addr : taddr);
+
+      begin
+         writeln;
+         writeln('Exception: ',s,' at $',qword2str(addr));
+         stopsim;
+      end;
+
+    constructor tmemorymanager.init;
+
+      begin
+         mem:=nil;
+      end;
+
+    procedure tmemorymanager.allocate(addr : taddr;size : qword);
+
+      var
+         ma : pmemoryarea;
+         asize : qword;
+
+      begin
+         while size>0 do
+           begin
+              if size>32768 then
+                asize:=32768
+              else
+                asize:=size;
+              size:=size-asize;
+              new(ma);
+              getmem(ma^.memory,trunc(asize));
+              fillchar(ma^.memory^,trunc(asize),0);
+              ma^.size:=trunc(asize);
+              ma^.addr:=addr;
+              addr:=addr+asize;
+
+              ma^.next:=mem;
+              mem:=ma;
+           end;
+      end;
+
+    function tmemorymanager.readq(addr : taddr) : qword;
+
+      var
+         h : qword;
+         ma : pmemoryarea;
+         qw : tqwordrec;
+
+      begin
+         ma:=mem;
+         while assigned(ma) do
+           begin
+              if (addr>=ma^.addr) and (addr<ma^.addr+ma^.size) then
+                begin
+                   if addr<ma^.addr+ma^.size-7 then
+                     begin
+                        move(ma^.memory^[trunc(addr-ma^.addr)],h,8);
+                        readq:=h;
+                        exit;
+                     end
+                   else
+                     begin
+                        qw.low32:=readd(addr);
+                        qw.high32:=readd(addr+4);
+                        readq:=comp(qw);
+                        exit;
+                     end;
+                end;
+              ma:=ma^.next;
+           end;
+         exception('Access violation to $'+qword2str(addr),instructionpc);
+      end;
+
+    function tmemorymanager.readalignedq(addr : taddr) : qword;
+
+      var
+         h : qword;
+         ma : pmemoryarea;
+         qw : tqwordrec;
+
+      begin
+         if (tqwordrec(addr).low32 and $7)<>0 then
+           exception('Alignment violation (dword) to $'+qword2str(addr),instructionpc);
+         ma:=mem;
+         while assigned(ma) do
+           begin
+              if (addr>=ma^.addr) and (addr<ma^.addr+ma^.size) then
+                begin
+                    move(ma^.memory^[trunc(addr-ma^.addr)],h,8);
+                    readalignedq:=h;
+                    exit;
+                end;
+              ma:=ma^.next;
+           end;
+         exception('Access violation to $'+qword2str(addr),instructionpc);
+      end;
+
+    function tmemorymanager.readd(addr : taddr) : dword;
+
+      var
+         h : dword;
+         ma : pmemoryarea;
+
+      begin
+         ma:=mem;
+         while assigned(ma) do
+           begin
+              if (addr>=ma^.addr) and (addr<ma^.addr+ma^.size) then
+                begin
+                   if addr<ma^.addr+ma^.size-3 then
+                     begin
+                        move(ma^.memory^[trunc(addr-ma^.addr)],h,4);
+                        readd:=h;
+                        exit;
+                     end
+                   else
+                     begin
+                        readd:=readb(addr)+readb(addr+1) shl 8+readb(addr+2) shl 16+
+                          readb(addr+3) shl 24;
+                        exit;
+                     end;
+                end;
+              ma:=ma^.next;
+           end;
+         exception('Access violation to $'+qword2str(addr),instructionpc);
+      end;
+
+    function tmemorymanager.readalignedd(addr : taddr) : dword;
+
+      var
+         h : dword;
+         ma : pmemoryarea;
+
+      begin
+         if (tqwordrec(addr).low32 and $3)<>0 then
+           exception('Alignment violation (dword) to $'+qword2str(addr),instructionpc);
+         ma:=mem;
+         while assigned(ma) do
+           begin
+              if (addr>=ma^.addr) and (addr<ma^.addr+ma^.size) then
+                begin
+                   move(ma^.memory^[trunc(addr-ma^.addr)],h,4);
+                   readalignedd:=h;
+                   exit;
+                end;
+              ma:=ma^.next;
+           end;
+         exception('Access violation to $'+qword2str(addr),instructionpc);
+      end;
+
+    function tmemorymanager.readb(addr : taddr) : dword;
+
+      var
+         ma : pmemoryarea;
+
+      begin
+         ma:=mem;
+         while assigned(ma) do
+           begin
+              if (addr>=ma^.addr) and (addr<ma^.addr+ma^.size) then
+                begin
+                   readb:=ma^.memory^[trunc(addr-ma^.addr)];
+                   exit;
+                end;
+              ma:=ma^.next;
+           end;
+         exception('Access violation to $'+qword2str(addr),instructionpc);
+      end;
+
+    procedure tmemorymanager.writeb(addr : taddr;b : byte);
+
+      var
+         ma : pmemoryarea;
+
+      begin
+         ma:=mem;
+         while assigned(ma) do
+           begin
+              if (addr>=ma^.addr) and (addr<ma^.addr+ma^.size) then
+                begin
+                   ma^.memory^[trunc(addr-ma^.addr)]:=b;
+                   exit;
+                end;
+              ma:=ma^.next;
+           end;
+         exception('Access violation to $'+qword2str(addr),instructionpc);
+      end;
+
+    procedure tmemorymanager.writed(addr : taddr;d : dword);
+
+      begin
+         writeb(addr,tdword(d)[0]);
+         writeb(addr+1,tdword(d)[1]);
+         writeb(addr+2,tdword(d)[2]);
+         writeb(addr+3,tdword(d)[3]);
+      end;
+
+    procedure tmemorymanager.writealignedd(addr : taddr;d : dword);
+
+      begin
+         writeb(addr,tdword(d)[0]);
+         writeb(addr+1,tdword(d)[1]);
+         writeb(addr+2,tdword(d)[2]);
+         writeb(addr+3,tdword(d)[3]);
+      end;
+
+    procedure tmemorymanager.writeq(addr : taddr;q : qword);
+
+      var
+         ma : pmemoryarea;
+
+      begin
+         ma:=mem;
+         while assigned(ma) do
+           begin
+              if (addr>=ma^.addr) and (addr<ma^.addr+ma^.size-7) then
+                begin
+                   move(q,ma^.memory^[trunc(addr-ma^.addr)],8);
+                   exit;
+                end
+              else
+                { misaligned write! }
+                if (addr>=ma^.addr) and (addr<ma^.addr+ma^.size) then
+                  begin
+                     writeln('Not implemented 1!');
+                     halt(1);
+                  end;
+              ma:=ma^.next;
+           end;
+         exception('Access violation to $'+qword2str(addr),instructionpc);
+      end;
+
+end.
+{
+  $Log$
+  Revision 1.1  1999-06-14 11:49:48  florian
+    + initial revision, it runs simple Alpha Linux ELF executables
+       - integer operations are nearly completed (non with overflow checking)
+       - floating point operations aren't implemented (except loading and
+         storing)
+       - only the really necessary system calls are implemented by dummys
+         write syscalls are redirected to the console
+
+}

+ 122 - 0
utils/simulator/simbase.pas

@@ -0,0 +1,122 @@
+{
+    $Id$
+    This file is part of the Free Pascal simulator environment
+    Copyright (c) 1999 by Florian Klaempfl
+
+    This unit implemements some helper routines
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+{$N+}
+unit simbase;
+
+  interface
+
+    uses
+       dos;
+
+    { global types }
+    type
+       { tindex must be at least of type integer }
+       tindex = integer;
+
+       int64 = comp;
+       qword = comp;
+
+       dword = longint;
+       tdword = array[0..3] of byte;
+
+       pbyte = ^byte;
+       pword = ^word;
+       pdword = ^dword;
+       pqword = ^qword;
+
+       tqwordrec = record
+          case tindex of
+             1 : (low32,high32 : dword);
+             2 : (bytes : array[0..7] of byte);
+             3 : (words : array[0..3] of word);
+       end;
+
+       oword = array[0..7] of word;
+
+       towordrec = record
+          case tindex of
+             1 : (bytes : array[0..15] of byte);
+             2 : (words : array[0..7] of word);
+             3 : (low64,high64 : qword);
+       end;
+
+    function hexstr(val : longint;cnt : byte) : string;
+    function qword2str(q : qword) : string;
+    function realtime : double;
+
+    var
+       stopsim : procedure;
+
+  implementation
+
+    function hexstr(val : longint;cnt : byte) : string;
+
+       const
+          HexTbl : array[0..15] of char='0123456789ABCDEF';
+
+       var
+         i : tindex;
+
+       begin
+          hexstr[0]:=char(cnt);
+          for i:=cnt downto 1 do
+            begin
+               hexstr[i]:=hextbl[val and $f];
+               val:=val shr 4;
+            end;
+       end;
+
+    function qword2str(q : qword) : string;
+
+      begin
+         qword2str:=hexstr(tqwordrec(q).high32,8)+hexstr(tqwordrec(q).low32,8);
+      end;
+
+    function realtime : double;
+
+      var
+         h,m,s,s100 : word;
+
+      begin
+         gettime(h,m,s,s100);
+         realtime:=h*3600+m*60+s+s100/100.0;
+      end;
+
+    procedure _stopsim;{$ifdef TP}far;{$endif TP}
+
+      begin
+         writeln('Simulation stopped');
+         halt(1);
+      end;
+
+begin
+   {$ifdef FPC}
+   stopsim:=@_stopsim;
+   {$else FPC}
+   stopsim:=_stopsim;
+   {$endif FPC}
+end.
+{
+  $Log$
+  Revision 1.1  1999-06-14 11:49:48  florian
+    + initial revision, it runs simple Alpha Linux ELF executables
+       - integer operations are nearly completed (non with overflow checking)
+       - floating point operations aren't implemented (except loading and
+         storing)
+       - only the really necessary system calls are implemented by dummys
+         write syscalls are redirected to the console
+
+}

+ 237 - 0
utils/simulator/simlib.pas

@@ -0,0 +1,237 @@
+{
+    $Id$
+    This file is part of the Free Pascal simulator environment
+    Copyright (c) 1999 by Florian Klaempfl
+
+    This unit implemements routines for data types which aren't
+    support by commonly used compilers
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+{$N+}
+{ we do some strange things here }
+{$O-}
+{$R-}
+unit simlib;
+
+  interface
+
+    uses
+       simbase;
+
+    procedure byte_zap(q : qword;b : byte;var result : qword);
+
+    { shifts q b bytes left }
+    procedure shift_left_q(q : qword;b : byte;var result : qword);
+
+    { shifts q b bytes right }
+    procedure shift_right_q(q : qword;b : byte;var result : qword);
+
+    { returns true if i1<i2 assuming that c1 and c2 are unsigned !}
+    function ltu(c1,c2 : comp) : boolean;
+
+    { returns true if i1=<i2 assuming that c1 and c2 are unsigned !}
+    function leu(c1,c2 : comp) : boolean;
+
+    { adds to owords, returns true if an overflow occurs }
+    function addoword(o1,o2 : oword;var result : oword) : boolean;
+
+    { adds two words, returns true if an overflow occurs }
+    function addword(w1,w2 : word;var result : word) : boolean;
+
+    { sets an oword to zero }
+    procedure zerooword(var o : oword);
+
+    { multiplies two qwords into a full oword }
+    procedure mulqword(q1,q2 : qword;var result : oword);
+
+  implementation
+
+    procedure byte_zap(q : qword;b : byte;var result : qword);
+
+      var
+         i : tindex;
+
+      begin
+         for i:=0 to 7 do
+           if ((1 shl i) and b)=0 then
+             tqwordrec(result).bytes[i]:=tqwordrec(q).bytes[i]
+           else
+             tqwordrec(result).bytes[i]:=0;
+      end;
+
+    { shifts q b bytes left }
+    procedure shift_left_q(q : qword;b : byte;var result : qword);
+
+      var
+         i : tindex;
+
+      begin
+         result:=0;
+         if b>63 then
+         else if b>31 then
+           tqwordrec(result).high32:=tqwordrec(q).low32 shl (b-32)
+         else
+           begin
+              { bad solution! A qword shift would be nice! }
+              result:=q;
+              for i:=1 to b do
+                begin
+                   tqwordrec(result).high32:=tqwordrec(result).high32 shl 1;
+                   if (tqwordrec(result).low32 and $80000000)<>0 then
+                     tqwordrec(result).high32:=tqwordrec(result).high32 or 1;
+                   tqwordrec(result).low32:=tqwordrec(result).low32 shl 1;
+                end;
+           end;
+      end;
+
+    { shifts q b bytes right }
+    procedure shift_right_q(q : qword;b : byte;var result : qword);
+
+      var
+         i : tindex;
+
+      begin
+         result:=0;
+         if b>63 then
+         else if b>31 then
+           tqwordrec(result).low32:=tqwordrec(q).high32 shr (b-32)
+         else
+           begin
+              { bad solution! A qword shift would be nice! }
+              result:=q;
+              for i:=1 to b do
+                begin
+                   tqwordrec(result).low32:=tqwordrec(result).low32 shr 1;
+                   if (tqwordrec(result).high32 and 1)<>0 then
+                     tqwordrec(result).low32:=tqwordrec(result).low32 or
+                       $80000000;
+                   tqwordrec(result).high32:=tqwordrec(result).high32 shr 1;
+                end;
+           end;
+      end;
+
+    { returns true if i1<i2 assuming that c1 and c2 are unsigned !}
+    function ltu(c1,c2 : comp) : boolean;
+
+      begin
+         if (c1>=0) and (c2>=0) then
+           ltu:=c1<c2
+         else if (c1<0) and (c2>=0) then
+           ltu:=false
+         else if (c1>=0) and (c2<0) then
+           ltu:=true
+         else
+           ltu:=c1<c2
+      end;
+
+    { returns true if i1=<i2 assuming that c1 and c2 are unsigned !}
+    function leu(c1,c2 : comp) : boolean;
+
+      begin
+         if (c1>=0) and (c2>=0) then
+           leu:=c1<=c2
+         else if (c1<0) and (c2>=0) then
+           leu:=false
+         else if (c1>=0) and (c2<0) then
+           leu:=true
+         else
+           leu:=c1<=c2
+      end;
+
+    { "ands" two qwords }
+    procedure andqword(w1,w2 : qword;var result : qword);
+
+      begin
+         tqwordrec(result).low32:=tqwordrec(w1).low32 and tqwordrec(w2).low32;
+         tqwordrec(result).high32:=tqwordrec(w1).high32 and tqwordrec(w2).high32;
+      end;
+
+    { adds two words, returns true if an overflow occurs }
+    function addword(w1,w2 : word;var result : word) : boolean;
+
+      var
+         l : longint;
+
+      begin
+         l:=w1+w2;
+         addword:=(l and $10000)<>0;
+         result:=l and $ffff;
+      end;
+
+    { adds two owords, returns true if an overflow occurs }
+    function addoword(o1,o2 : oword;var result : oword) : boolean;
+
+      var
+         i : tindex;
+         carry : word;
+
+      begin
+         carry:=0;
+         for i:=0 to 7 do
+           begin
+              result[i]:=o1[i]+o2[i]+carry;
+              { an overflow has occured, if the result is less
+                than one of the summands
+              }
+              if (result[i]<o1[i]) or (result[i]<o2[i]) then
+                carry:=1
+              else
+                carry:=0;
+           end;
+         addoword:=carry=1;
+      end;
+
+    { sets an oword to zero }
+    procedure zerooword(var o : oword);
+
+      begin
+         fillchar(o,sizeof(o),0);
+      end;
+
+    { multiplies two qwords into a full oword }
+    procedure mulqword(q1,q2 : qword;var result : oword);
+
+      var
+         i : tindex;
+         h,bitpos : qword;
+         ho1 : oword;
+
+      begin
+         { result is zero }
+         zerooword(ho1);
+         result:=ho1;
+         towordrec(ho1).low64:=q1;
+
+         bitpos:=1;
+
+         for i:=0 to 63 do
+           begin
+              andqword(q2,bitpos,h);
+              if h<>0 then
+                addoword(result,ho1,result);
+
+              { ho1:=2*ho1 }
+              addoword(ho1,ho1,ho1);
+              shift_left_q(bitpos,1,bitpos);
+           end;
+      end;
+
+end.
+{
+  $Log$
+  Revision 1.1  1999-06-14 11:49:48  florian
+    + initial revision, it runs simple Alpha Linux ELF executables
+       - integer operations are nearly completed (non with overflow checking)
+       - floating point operations aren't implemented (except loading and
+         storing)
+       - only the really necessary system calls are implemented by dummys
+         write syscalls are redirected to the console
+
+}