123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275 |
- {
- This file is part of the Free Pascal simulator environment
- Copyright (c) 1999-2000 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
- {$ifdef delphi}
- dmisc,
- {$else}
- dos,
- {$endif}
- 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 = packed 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 = packed 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
- {$ifdef fpc}
- { 64kB Stacksize }
- stacksize = 64*1024;
- { stack start at 4 GB }
- stackstart : dword = 1024*1024*1024*4-stacksize;
- {$else fpc}
- { 64kB Stacksize }
- stacksize = 64*1024.0;
- { stack start at 4 GB }
- stackstart = 1024.0*1024.0*1024.0*4-stacksize;
- {$endif fpc}
- { 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,' 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;
- 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 : taddr);
- var
- instruction : tinstruction;
- rega,regb,regc : tindex;
- lit : byte;
- va : tintreg;
- function getbranchdisp : int64;
- 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+int64(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+
- (int64(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+
- (int64(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+
- (int64(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].valueq:=state.r[rega].valueq xor
- valueqb;
- 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].valueq:=valueqa xor
- not(valueqb);
- 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
- state.r[regc].valueq:=state.r[regc].valueq shr (valueqb and $3f);
- 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+
- (int64(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+
- (int64(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+
- (int64(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+
- (int64(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+
- (int64(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+
- (int64(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+
- (int64(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+
- (int64(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+
- (int64(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+
- (int64(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.
|