#!/usr/bin/perl -w # $Id: tmuconv 1089 2018-12-19 10:45:41Z mueller $ # # Copyright 2008-2018 by Walter F.J. Mueller # # This program is free software; you may redistribute and/or modify it under # the terms of the GNU General Public License as published by the Free # Software Foundation, either version 3, or (at your option) any later version. # # 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. See the GNU General Public License # for complete details. # # Revision History: # Date Rev Version Comment # 2018-12-18 1089 1.1.3 add and use bailout # 2018-10-05 1053 1.1.2 use 'ca.*' instead of 'sy.*' fields # 2015-11-01 712 1.1.1 BUGFIX: fix '.' handling for br/sob instructions # BUGFIX: correct xor (now r,dst, and not src,r) # br/sob offsets now octal; assume --t_id if no opts # 2015-07-03 697 1.1 adapt to new DM_STAT_(SY|VM); add rhrp vector # 2010-10-22 334 1.0.9 adapt to ibus V2 signals: req,we,dip->aval,re,we,rmw # 2010-06-26 309 1.0.8 add ibimres.cacc/racc handling # 2010-04-26 284 1.0.7 add error check for GetOptions # 2009-09-19 240 1.0.6 add more VFETCH addr defs; add 2nd DL11 defs # 2009-06-04 223 1.0.5 add IIST and PC11 defs # 2009-05-03 212 1.0.4 add defs for mmu par/pdr's and some unibus dev's # 2008-12-14 177 1.0.3 add -t_ru; use dp_ireg_we_last; add ibus names # 2008-11-30 174 1.0.2 SPUSH and VFETCH tags for em cycles; psw in id lines # 2008-04-25 138 1.0.1 show ccc/scc for code 000257/000277 in disassembler # 2008-04-19 137 1.0 Initial version # # Current fields in tmu_ofile: # clkcycle:d # cpu:o # dp.pc:o # dp.psw:o # dp.ireg:o # dp.ireg_we:b # dp.ireg_we_last:b # dp.dsrc:o # dp.ddst:o # dp.dtmp:o # dp.dres:o # dp.gpr_adst:o # dp.gpr_mode:o # dp.gpr_bytop:b # dp.gpr_we:b # vm.ibmreq.aval:b # vm.ibmreq.re:b # vm.ibmreq.we:b # vm.ibmreq.rmw:b # vm.ibmreq.be0:b # vm.ibmreq.be1:b # vm.ibmreq.cacc:b # vm.ibmreq.racc:b # vm.ibmreq.addr:o # vm.ibmreq.din:o # vm.ibsres.ack:b # vm.ibsres.busy:b # vm.ibsres.dout:o # vm.emmreq.req:b # vm.emmreq.we:b # vm.emmreq.be:b # vm.emmreq.cancel:b # vm.emmreq.addr:o # vm.emmreq.din:o # vm.emsres.ack_r:b # vm.emsres.ack_w:b # vm.emsres.dout:o # co.cpugo:b # co.cpususp:b # co.suspint:b # co.suspext:b # ca.rd:b # ca.wr:b # ca.rdhit:b # ca.wrhit:b # ca.rdmem:b # ca.wrmem:b # ca.rdwait:b # ca.wrwait:b # use 5.14.0; # require Perl 5.14 or higher use strict; # require strict checking use FileHandle; use Getopt::Long; my %opts = (); GetOptions(\%opts, "help", "dump", "cdump", "t_id", "t_ru", "t_em", "t_ib") or bailout("bad command options"); my @var_name; my @var_type; my @var_dec; my @var_oct; my %name; my @val_curr_text; my @val_curr; my @val_last; my @reg_05 = ("------","------","------","------","------","------", # set 0 "------","------","------","------","------","------",); # set 1 my @reg_sp = ("------","------","------","------"); # ksp,ssp,???,usp my $ind_dp_pc; my $ind_dp_psw; my $ind_dp_ireg; my $ind_dp_ireg_we; my $ind_dp_ireg_we_last; my $ind_dp_dres; my $ind_dp_gpr_adst; my $ind_dp_gpr_mode; my $ind_dp_gpr_bytop; my $ind_dp_gpr_we; my $ind_vm_ibmreq_aval; my $ind_vm_ibmreq_re; my $ind_vm_ibmreq_we; my $ind_vm_ibmreq_rmw; my $ind_vm_ibmreq_be0; my $ind_vm_ibmreq_be1; my $ind_vm_ibmreq_cacc; my $ind_vm_ibmreq_racc; my $ind_vm_ibmreq_addr; my $ind_vm_ibmreq_din; my $ind_vm_ibsres_ack; my $ind_vm_ibsres_busy; my $ind_vm_ibsres_dout; my $ind_vm_emmreq_req; my $ind_vm_emmreq_we; my $ind_vm_emmreq_be; my $ind_vm_emmreq_cancel; my $ind_vm_emmreq_addr; my $ind_vm_emmreq_din; my $ind_vm_emsres_ack_r; my $ind_vm_emsres_ack_w; my $ind_vm_emsres_dout; my $ind_ca_rd; my $ind_ca_wr; my $ind_ca_rdhit; my $ind_ca_wrhit; my $ind_ca_rdmem; my $ind_ca_wrmem; my $ind_ca_rdwait; my $ind_ca_wrwait; my @pdp11_opcode_tbl = ( {code=>0000000, mask=>0000000, name=>"halt", type=>"0arg"}, {code=>0000001, mask=>0000000, name=>"wait", type=>"0arg"}, {code=>0000002, mask=>0000000, name=>"rti ", type=>"0arg"}, {code=>0000003, mask=>0000000, name=>"bpt ", type=>"0arg"}, {code=>0000004, mask=>0000000, name=>"iot ", type=>"0arg"}, {code=>0000005, mask=>0000000, name=>"reset",type=>"0arg"}, {code=>0000006, mask=>0000000, name=>"rtt ", type=>"0arg"}, {code=>0000007, mask=>0000000, name=>"!!mfpt", type=>"0arg"}, {code=>0000100, mask=>0000077, name=>"jmp ", type=>"1arg"}, {code=>0000200, mask=>0000007, name=>"rts ", type=>"1reg"}, {code=>0000230, mask=>0000007, name=>"spl ", type=>"spl"}, {code=>0000240, mask=>0000017, name=>"cl", type=>"ccop"}, {code=>0000260, mask=>0000017, name=>"se", type=>"ccop"}, {code=>0000300, mask=>0000077, name=>"swab", type=>"1arg"}, {code=>0000400, mask=>0000377, name=>"br ", type=>"br"}, {code=>0001000, mask=>0000377, name=>"bne ", type=>"br"}, {code=>0001400, mask=>0000377, name=>"beq ", type=>"br"}, {code=>0002000, mask=>0000377, name=>"bge ", type=>"br"}, {code=>0002400, mask=>0000377, name=>"blt ", type=>"br"}, {code=>0003000, mask=>0000377, name=>"bgt ", type=>"br"}, {code=>0003400, mask=>0000377, name=>"ble ", type=>"br"}, {code=>0004000, mask=>0000777, name=>"jsr ", type=>"rsrc"}, {code=>0005000, mask=>0000077, name=>"clr ", type=>"1arg"}, {code=>0005100, mask=>0000077, name=>"com ", type=>"1arg"}, {code=>0005200, mask=>0000077, name=>"inc ", type=>"1arg"}, {code=>0005300, mask=>0000077, name=>"dec ", type=>"1arg"}, {code=>0005400, mask=>0000077, name=>"neg ", type=>"1arg"}, {code=>0005500, mask=>0000077, name=>"adc ", type=>"1arg"}, {code=>0005600, mask=>0000077, name=>"sbc ", type=>"1arg"}, {code=>0005700, mask=>0000077, name=>"tst ", type=>"1arg"}, {code=>0006000, mask=>0000077, name=>"ror ", type=>"1arg"}, {code=>0006100, mask=>0000077, name=>"rol ", type=>"1arg"}, {code=>0006200, mask=>0000077, name=>"asr ", type=>"1arg"}, {code=>0006300, mask=>0000077, name=>"asl ", type=>"1arg"}, {code=>0006400, mask=>0000077, name=>"mark", type=>"mark"}, {code=>0006500, mask=>0000077, name=>"mfpi", type=>"1arg"}, {code=>0006600, mask=>0000077, name=>"mtpi", type=>"1arg"}, {code=>0006700, mask=>0000077, name=>"sxt ", type=>"1arg"}, {code=>0007000, mask=>0000077, name=>"!!csm", type=>"1arg"}, {code=>0007200, mask=>0000077, name=>"!!tstset",type=>"1arg"}, {code=>0007300, mask=>0000077, name=>"!!wrtlck",type=>"1arg"}, {code=>0010000, mask=>0007777, name=>"mov ", type=>"2arg"}, {code=>0020000, mask=>0007777, name=>"cmp ", type=>"2arg"}, {code=>0030000, mask=>0007777, name=>"bit ", type=>"2arg"}, {code=>0040000, mask=>0007777, name=>"bic ", type=>"2arg"}, {code=>0050000, mask=>0007777, name=>"bis ", type=>"2arg"}, {code=>0060000, mask=>0007777, name=>"add ", type=>"2arg"}, {code=>0070000, mask=>0000777, name=>"mul ", type=>"rdst"}, {code=>0071000, mask=>0000777, name=>"div ", type=>"rdst"}, {code=>0072000, mask=>0000777, name=>"ash ", type=>"rdst"}, {code=>0073000, mask=>0000777, name=>"ashc", type=>"rdst"}, {code=>0074000, mask=>0000777, name=>"xor ", type=>"rsrc"}, {code=>0077000, mask=>0000777, name=>"sob ", type=>"sob"}, {code=>0100000, mask=>0000377, name=>"bpl ", type=>"br"}, {code=>0100400, mask=>0000377, name=>"bmi ", type=>"br"}, {code=>0101000, mask=>0000377, name=>"bhi ", type=>"br"}, {code=>0101400, mask=>0000377, name=>"blos", type=>"br"}, {code=>0102000, mask=>0000377, name=>"bvc ", type=>"br"}, {code=>0102400, mask=>0000377, name=>"bvs ", type=>"br"}, {code=>0103000, mask=>0000377, name=>"bcc ", type=>"br"}, {code=>0103400, mask=>0000377, name=>"bcs ", type=>"br"}, {code=>0104000, mask=>0000377, name=>"emt ", type=>"trap"}, {code=>0104400, mask=>0000377, name=>"trap", type=>"trap"}, {code=>0105000, mask=>0000077, name=>"clrb", type=>"1arg"}, {code=>0105100, mask=>0000077, name=>"comb", type=>"1arg"}, {code=>0105200, mask=>0000077, name=>"incb", type=>"1arg"}, {code=>0105300, mask=>0000077, name=>"decb", type=>"1arg"}, {code=>0105400, mask=>0000077, name=>"negb", type=>"1arg"}, {code=>0105500, mask=>0000077, name=>"adcb", type=>"1arg"}, {code=>0105600, mask=>0000077, name=>"sbcb", type=>"1arg"}, {code=>0105700, mask=>0000077, name=>"tstb", type=>"1arg"}, {code=>0106000, mask=>0000077, name=>"rorb", type=>"1arg"}, {code=>0106100, mask=>0000077, name=>"rolb", type=>"1arg"}, {code=>0106200, mask=>0000077, name=>"asrb", type=>"1arg"}, {code=>0106300, mask=>0000077, name=>"aslb", type=>"1arg"}, {code=>0106400, mask=>0000077, name=>"!!mtps", type=>"1arg"}, {code=>0106500, mask=>0000077, name=>"mfpd", type=>"1arg"}, {code=>0106600, mask=>0000077, name=>"mtpd", type=>"1arg"}, {code=>0106700, mask=>0000077, name=>"!!mfps", type=>"1arg"}, {code=>0110000, mask=>0007777, name=>"movb", type=>"2arg"}, {code=>0120000, mask=>0007777, name=>"cmpb", type=>"2arg"}, {code=>0130000, mask=>0007777, name=>"bitb", type=>"2arg"}, {code=>0140000, mask=>0007777, name=>"bicb", type=>"2arg"}, {code=>0150000, mask=>0007777, name=>"bisb", type=>"2arg"}, {code=>0160000, mask=>0007777, name=>"sub ", type=>"2arg"}, {code=>0170000, mask=>0000000, name=>"!!cfcc", type=>"0arg"}, {code=>0170001, mask=>0000000, name=>"!!setf", type=>"0arg"}, {code=>0170011, mask=>0000000, name=>"!!setd", type=>"0arg"}, {code=>0170002, mask=>0000000, name=>"!!seti", type=>"0arg"}, {code=>0170012, mask=>0000000, name=>"!!setl", type=>"0arg"}, {code=>0170100, mask=>0000077, name=>"!!ldfps",type=>"1fpp"}, {code=>0170200, mask=>0000077, name=>"!!stfps",type=>"1fpp"}, {code=>0170300, mask=>0000077, name=>"!!stst", type=>"1fpp"}, {code=>0170400, mask=>0000077, name=>"!!clrf", type=>"1fpp"}, {code=>0170500, mask=>0000077, name=>"!!tstf", type=>"1fpp"}, {code=>0170600, mask=>0000077, name=>"!!absf", type=>"1fpp"}, {code=>0170700, mask=>0000077, name=>"!!negf", type=>"1fpp"}, {code=>0171000, mask=>0000377, name=>"!!mulf", type=>"rfpp"}, {code=>0171400, mask=>0000377, name=>"!!modf", type=>"rfpp"}, {code=>0172000, mask=>0000377, name=>"!!addf", type=>"rfpp"}, {code=>0172400, mask=>0000377, name=>"!!ldf", type=>"rfpp"}, {code=>0173000, mask=>0000377, name=>"!!subf", type=>"rfpp"}, {code=>0173400, mask=>0000377, name=>"!!cmpf", type=>"rfpp"}, {code=>0174000, mask=>0000377, name=>"!!stf", type=>"rfpp"}, {code=>0174400, mask=>0000377, name=>"!!divf", type=>"rfpp"}, {code=>0175000, mask=>0000377, name=>"!!stexp",type=>"rfpp"}, {code=>0175400, mask=>0000377, name=>"!!stcif",type=>"rfpp"}, {code=>0176000, mask=>0000377, name=>"!!stcfd",type=>"rfpp"}, {code=>0176400, mask=>0000377, name=>"!!ldexp",type=>"rfpp"}, {code=>0177000, mask=>0000377, name=>"!!ldcif",type=>"rfpp"}, {code=>0177400, mask=>0000377, name=>"!!ldcdf",type=>"rfpp"} ); my %pdp11_regs = ( # use simh naming convention 177776=> "psw", 177774=> "stklim", 177772=> "pirq", 177770=> "mbrk", 177766=> "cpuerr", 177764=> "sysid", 177600=> "uipdr0", 177602=> "uipdr1", 177604=> "uipdr2", 177606=> "uipdr3", 177610=> "uipdr4", 177612=> "uipdr5", 177614=> "uipdr6", 177616=> "uipdr7", 177620=> "udpdr0", 177622=> "udpdr1", 177624=> "udpdr2", 177626=> "udpdr3", 177630=> "udpdr4", 177632=> "udpdr5", 177634=> "udpdr6", 177636=> "udpdr7", 177640=> "uipar0", 177642=> "uipar1", 177644=> "uipar2", 177646=> "uipar3", 177650=> "uipar4", 177652=> "uipar5", 177654=> "uipar6", 177656=> "uipar7", 177660=> "udpar0", 177662=> "udpar1", 177664=> "udpar2", 177666=> "udpar3", 177670=> "udpar4", 177672=> "udpar5", 177674=> "udpar6", 177676=> "udpar7", 177576=> "mmr2", 177574=> "mmr1", 177572=> "mmr0", 177570=> "sdreg", # not a simh name !! 177560=> "tia.csr", 177562=> "tia.buf", 177564=> "toa.csr", 177566=> "toa.buf", 177550=> "pr.csr", 177552=> "pr.buf", 177554=> "pp.csr", 177556=> "pp.buf", 177546=> "kl.csr", 177514=> "lp.csr", 177516=> "lp.buf", 177500=> "ii.acr", 177502=> "ii.adr", 177400=> "rk.ds ", 177402=> "rk.er ", 177404=> "rk.cs ", 177406=> "rk.wc ", 177410=> "rk.ba ", 177412=> "rk.da ", 177414=> "rk.mr ", 177416=> "rk.db ", 177060=> "xor.cs", # XOR Tester 176700=> "rp.cs1", 176702=> "rp.wc ", 176704=> "rp.ba ", 176706=> "rp.da ", 176710=> "rp.cs2", 176712=> "rp.ds ", 176714=> "rp.er1", 176716=> "rp.as ", 176720=> "rp.la ", 176722=> "rp.db ", 176724=> "rp.mr1", 176726=> "rp.dt ", 176730=> "rp.sn ", 176732=> "rp.of ", 176734=> "rp.dc ", 176736=> "rp.m13", 176740=> "rp.m14", 176742=> "rp.m15", 176744=> "rp.ec1", 176746=> "rp.ec2", 176750=> "rp.bae", 176752=> "rp.cs3", 176500=> "tib.cs", 176502=> "tib.bu", 176504=> "tob.cs", 176506=> "tob.bu", 174400=> "rl.cs ", 174402=> "rl.ba ", 174404=> "rl.da ", 174406=> "rl.mp ", 172540=> "kp.csr", 172542=> "kp.buf", 172544=> "kp.cnt", 172520=> "tm.sr", 172522=> "tm.cr", 172524=> "tm.bc", 172526=> "tm.ba", 172530=> "tm.db", 172532=> "tm.rl", 172516=> "mmr3", 172200=> "sipdr0", 172202=> "sipdr1", 172204=> "sipdr2", 172206=> "sipdr3", 172210=> "sipdr4", 172212=> "sipdr5", 172214=> "sipdr6", 172216=> "sipdr7", 172220=> "sdpdr0", 172222=> "sdpdr1", 172224=> "sdpdr2", 172226=> "sdpdr3", 172230=> "sdpdr4", 172232=> "sdpdr5", 172234=> "sdpdr6", 172236=> "sdpdr7", 172240=> "sipar0", 172242=> "sipar1", 172244=> "sipar2", 172246=> "sipar3", 172250=> "sipar4", 172252=> "sipar5", 172254=> "sipar6", 172256=> "sipar7", 172260=> "sdpar0", 172262=> "sdpar1", 172264=> "sdpar2", 172266=> "sdpar3", 172270=> "sdpar4", 172272=> "sdpar5", 172274=> "sdpar6", 172276=> "sdpar7", 172300=> "kipdr0", 172302=> "kipdr1", 172304=> "kipdr2", 172306=> "kipdr3", 172310=> "kipdr4", 172312=> "kipdr5", 172314=> "kipdr6", 172316=> "kipdr7", 172320=> "kdpdr0", 172322=> "kdpdr1", 172324=> "kdpdr2", 172326=> "kdpdr3", 172330=> "kdpdr4", 172332=> "kdpdr5", 172334=> "kdpdr6", 172336=> "kdpdr7", 172340=> "kipar0", 172342=> "kipar1", 172344=> "kipar2", 172346=> "kipar3", 172350=> "kipar4", 172352=> "kipar5", 172354=> "kipar6", 172356=> "kipar7", 172360=> "kdpar0", 172362=> "kdpar1", 172364=> "kdpar2", 172366=> "kdpar3", 172370=> "kdpar4", 172372=> "kdpar5", 172374=> "kdpar6", 172376=> "kdpar7", 160100=> "dz.csr", 160102=> "dz.mp2", 160104=> "dz.tcr", 160106=> "dz.mp6" ); autoflush STDOUT 1 if (-p STDOUT); # autoflush if output into pipe if (exists $opts{help}) { print_help(); exit 0; } my $nopts = 0; # count options $nopts += 1 if $opts{dump}; $nopts += 1 if $opts{cdump}; $nopts += 1 if $opts{t_id}; $nopts += 1 if $opts{t_ru}; $nopts += 1 if $opts{t_em}; $nopts += 1 if $opts{t_ib}; $opts{t_id} = 1 if $nopts == 0; # if no opts, assume t_id foreach my $file (@ARGV) { do_file($file); } #------------------------------------------------------------------------------- sub do_file { my ($file) = @_; open IFILE,"<$file" or bailout("failed to open '$file': $!"); my $idec_cyc = 0; my $change_cyc = 0; my $emreq_cyc = 0; my $emreq_str = ""; my $ibreq_cyc = 0; my $ibreq_typ = ""; my $ibreq_str = ""; my $ibreq_nam = ""; my $emcurr_we = 0; # curr em write enable (or undef) my $emcurr_addr = undef; # curr em address my $emlast_we = 0; # prev em write enable (or undef) my $emlast_addr = undef; # prev em address while () { chomp; if (/^#\s+/) { @var_name = (); @var_type = (); my $dsc_str = $'; my @dsc_list = split /\s+/,$dsc_str; foreach my $dsc (@dsc_list) { if ($dsc =~ /^(.*):([bdo])$/) { my $ind = scalar(@var_name); $name{$1} = {ind=>$ind, typ=>$2}; push @var_name, $1; push @var_type, $2; push @var_dec, $ind if $2 eq "d"; push @var_oct, $ind if $2 eq "o"; } else { print "tmuconv-E: bad descriptor $dsc\n"; } } $ind_dp_pc = $name{'dp.pc'}->{ind}; $ind_dp_psw = $name{'dp.psw'}->{ind}; $ind_dp_ireg = $name{'dp.ireg'}->{ind}; $ind_dp_ireg_we = $name{'dp.ireg_we'}->{ind}; $ind_dp_ireg_we_last = $name{'dp.ireg_we_last'}->{ind}; $ind_dp_dres = $name{'dp.dres'}->{ind}; $ind_dp_gpr_adst = $name{'dp.gpr_adst'}->{ind}; $ind_dp_gpr_mode = $name{'dp.gpr_mode'}->{ind}; $ind_dp_gpr_bytop = $name{'dp.gpr_bytop'}->{ind}; $ind_dp_gpr_we = $name{'dp.gpr_we'}->{ind}; $ind_vm_ibmreq_aval = $name{'vm.ibmreq.aval'}->{ind}; $ind_vm_ibmreq_re = $name{'vm.ibmreq.re'}->{ind}; $ind_vm_ibmreq_we = $name{'vm.ibmreq.we'}->{ind}; $ind_vm_ibmreq_rmw = $name{'vm.ibmreq.rmw'}->{ind}; $ind_vm_ibmreq_be0 = $name{'vm.ibmreq.be0'}->{ind}; $ind_vm_ibmreq_be1 = $name{'vm.ibmreq.be1'}->{ind}; $ind_vm_ibmreq_cacc = $name{'vm.ibmreq.cacc'}->{ind}; $ind_vm_ibmreq_racc = $name{'vm.ibmreq.racc'}->{ind}; $ind_vm_ibmreq_addr = $name{'vm.ibmreq.addr'}->{ind}; $ind_vm_ibmreq_din = $name{'vm.ibmreq.din'}->{ind}; $ind_vm_ibsres_ack = $name{'vm.ibsres.ack'}->{ind}; $ind_vm_ibsres_busy = $name{'vm.ibsres.busy'}->{ind}; $ind_vm_ibsres_dout = $name{'vm.ibsres.dout'}->{ind}; $ind_vm_emmreq_req = $name{'vm.emmreq.req'}->{ind}; $ind_vm_emmreq_we = $name{'vm.emmreq.we'}->{ind}; $ind_vm_emmreq_be = $name{'vm.emmreq.be'}->{ind}; $ind_vm_emmreq_cancel = $name{'vm.emmreq.cancel'}->{ind}; $ind_vm_emmreq_addr = $name{'vm.emmreq.addr'}->{ind}; $ind_vm_emmreq_din = $name{'vm.emmreq.din'}->{ind}; $ind_vm_emsres_ack_r = $name{'vm.emsres.ack_r'}->{ind}; $ind_vm_emsres_ack_w = $name{'vm.emsres.ack_w'}->{ind}; $ind_vm_emsres_dout = $name{'vm.emsres.dout'}->{ind}; $ind_ca_rd = $name{'ca.rd'}->{ind}; $ind_ca_wr = $name{'ca.wr'}->{ind}; $ind_ca_rdhit = $name{'ca.rdhit'}->{ind}; $ind_ca_wrhit = $name{'ca.wrhit'}->{ind}; $ind_ca_rdmem = $name{'ca.rdmem'}->{ind}; $ind_ca_wrmem = $name{'ca.wrmem'}->{ind}; $ind_ca_rdwait = $name{'ca.rdwait'}->{ind}; $ind_ca_wrwait = $name{'ca.wrwait'}->{ind}; } else { @val_last = @val_curr; my $notfirst = scalar(@val_last) > 0; $_ =~ s/^\s*//; $_ =~ s/\s*$//; @val_curr = split /\s+/,$_; if (scalar(@val_curr) != scalar(@var_name)) { printf "tmuconv-E: value list length mismatch, seen %d, expected %d\n", scalar(@val_curr), scalar(@var_name); for (my $i=0; $i>11 & 01; $ru_str = sprintf "%o %o%o %6.6o", $bytop, $rset, $adst, $dres; $ru_str .= " "; if ($adst eq "7") { $ru_str .= "pc"; } elsif ($adst eq "6") { $reg_sp[$mode] = sprintf "%6.6o",$dres; $ru_str .= $reg_sp[0]; $ru_str .= ($mode == 0) ? "*" : " "; $ru_str .= $reg_sp[1]; $ru_str .= ($mode == 1) ? "*" : " "; $ru_str .= $reg_sp[3]; $ru_str .= ($mode == 3) ? "*" : " "; $ru_str .= " ksp" if $mode eq "0"; $ru_str .= " ssp" if $mode eq "1"; $ru_str .= " usp" if $mode eq "3"; } else { my $rbase = ($rset==0) ? 0 : 6; $reg_05[$rbase+$adst] = sprintf "%6.6o",$dres; for (my $i=0; $i<6; $i++) { $ru_str .= $reg_05[$rbase+$i]; $ru_str .= ($adst==$i) ? "*" : " "; } $ru_str .= sprintf " r%o%o", $rset, $adst; } } } # # handle t_em # uses cycles with vm_emmreq_req = '1' # vm_emsres_ack_r = '1' # vm_emsres_ack_w = '1' # vm_emsreq_cancel = '1' # if (exists $opts{t_em}) { if ($val_curr[$ind_vm_emmreq_req]) { $emreq_cyc = $cyc_curr; $emreq_str = sprintf "%s %s %8.8o", ($val_curr[$ind_vm_emmreq_we] ? "w" : "r"), $val_curr[$ind_vm_emmreq_be], $val_curr[$ind_vm_emmreq_addr]; $emcurr_we = $val_curr[$ind_vm_emmreq_we]; $emcurr_addr = $val_curr[$ind_vm_emmreq_addr]; if ($emcurr_we) { $emreq_str .= sprintf " %6.6o", $val_curr[$ind_vm_emmreq_din]; } else { $emreq_str .= " " x 7; } } if ($val_curr[$ind_vm_emsres_ack_r] || $val_curr[$ind_vm_emsres_ack_w] || $val_curr[$ind_vm_emmreq_cancel]) { $emres_str = sprintf "%s%s%s%s", $val_curr[$ind_vm_emmreq_cancel], $val_curr[$ind_vm_emsres_ack_r], $val_curr[$ind_vm_emsres_ack_w], $val_curr[$ind_ca_rdhit]; if ($val_curr[$ind_vm_emmreq_cancel]) { $emreq_str .= " cancel"; $emcurr_we = undef; } else { if ($val_curr[$ind_vm_emsres_ack_r]) { $emreq_str .= sprintf " %6.6o", $val_curr[$ind_vm_emsres_dout]; } else { $emreq_str .= " " x 7; } if (defined $emlast_we && $emcurr_we == $emlast_we) { if ($emcurr_we && $emcurr_addr == $emlast_addr-2) { $emtyp_str = "SPUSH"; } elsif ((not $emcurr_we) && $emcurr_addr == $emlast_addr+2 && $emcurr_addr < 0400 && ($emcurr_addr % 04) == 02) { $emtyp_str = "VFETCH"; $emtyp_str .= " 004 ill.inst" if ($emlast_addr == 0004); $emtyp_str .= " 010 res.inst" if ($emlast_addr == 0010); $emtyp_str .= " 014 BPT" if ($emlast_addr == 0014); $emtyp_str .= " 020 IOT" if ($emlast_addr == 0020); $emtyp_str .= " 030 EMT" if ($emlast_addr == 0030); $emtyp_str .= " 034 TRAP" if ($emlast_addr == 0034); $emtyp_str .= " 060 DL11-TTI" if ($emlast_addr == 0060); $emtyp_str .= " 064 DL11-TTO" if ($emlast_addr == 0064); $emtyp_str .= " 070 PC11-PTR" if ($emlast_addr == 0070); $emtyp_str .= " 074 PC11-PTP" if ($emlast_addr == 0074); $emtyp_str .= " 100 KW11-L" if ($emlast_addr == 0100); $emtyp_str .= " 104 KW11-P" if ($emlast_addr == 0104); $emtyp_str .= " 160 RL11" if ($emlast_addr == 0160); $emtyp_str .= " 200 LP11" if ($emlast_addr == 0200); $emtyp_str .= " 220 RK11" if ($emlast_addr == 0220); $emtyp_str .= " 224 TM11" if ($emlast_addr == 0224); $emtyp_str .= " 240 PIRQ" if ($emlast_addr == 0240); $emtyp_str .= " 244 FPP exp" if ($emlast_addr == 0244); $emtyp_str .= " 250 MMU trap" if ($emlast_addr == 0250); $emtyp_str .= " 254 RHRP" if ($emlast_addr == 0254); $emtyp_str .= " 260 IIST" if ($emlast_addr == 0260); $emtyp_str .= " 300 DL11-2-TTI" if ($emlast_addr == 0300); $emtyp_str .= " 304 DL11-2-TTO" if ($emlast_addr == 0304); } } } $emlast_we = $emcurr_we; $emlast_addr = $emcurr_addr; } } # # handle t_ib # uses cycles with sy_ibmreq_re = '1' or sy_ibmreq_we = '1' # sy_ibsres_ack = '1' # vm_ibsres_busy '1' -> '0' transition # if (exists $opts{t_ib}) { if ($val_curr[$ind_vm_ibmreq_re] || $val_curr[$ind_vm_ibmreq_we]) { my $addr_str = sprintf "%6.6o", $val_curr[$ind_vm_ibmreq_addr]; $ibreq_cyc = $cyc_curr; $ibreq_typ = sprintf "%s%s", ($val_curr[$ind_vm_ibmreq_cacc] ? "c" : "-"), ($val_curr[$ind_vm_ibmreq_racc] ? "r" : "-"); $ibreq_str = sprintf "%s%s%s%s %s", ($val_curr[$ind_vm_ibmreq_we] ? "w" : "r"), ($val_curr[$ind_vm_ibmreq_rmw] ? "m" : " "), $val_curr[$ind_vm_ibmreq_be1], $val_curr[$ind_vm_ibmreq_be0], $addr_str; $ibreq_we = $val_curr[$ind_vm_ibmreq_we]; $ibreq_act = 1; if ($ibreq_we) { $ibreq_str .= sprintf " %6.6o", $val_curr[$ind_vm_ibmreq_din]; } else { $ibreq_str .= " " x 7; } $ibreq_nam = $pdp11_regs{$addr_str}; $ibreq_nam = "" if not defined $ibreq_nam; } if ($val_curr[$ind_vm_ibsres_ack]) { $ibreq_act = 0; $ibres_str .= sprintf " %s", $val_curr[$ind_vm_ibsres_ack]; if (not $ibreq_we) { $ibreq_str .= sprintf " %6.6o", $val_curr[$ind_vm_ibsres_dout]; } else { $ibreq_str .= " " x 7; } } if ($ibreq_act && $val_curr[$ind_vm_ibsres_busy]==0) { $ibres_str .= "no ACK, no BUSY"; $ibreq_act = 0; } } print "$cyc_str id $id_str\n" if $id_str; print "$cyc_str ru $ru_str\n" if $ru_str; if ($emres_str) { printf "$cyc_str em $emreq_str $emres_str (%d) $emtyp_str\n", $cyc_curr-$emreq_cyc; } if ($ibres_str) { printf "$cyc_str ib %s $ibreq_str $ibres_str (%d) $ibreq_nam\n", $ibreq_typ, $cyc_curr-$ibreq_cyc; } } } close IFILE; } #------------------------------------------------------------------------------- sub code2mnemo { my ($code) = @_; foreach my $ele (@pdp11_opcode_tbl) { if (($code & (~($ele->{mask})) ) == $ele->{code}) { my $name = $ele->{name}; my $type = $ele->{type}; my $str = $name; if ($type eq "0arg") { return $name; } elsif ($type eq "1arg" or $type eq "1fpp") { my $dst = $code & 077; my $dst_str = regmod($dst); return "$name $dst_str"; } elsif ($type eq "2arg") { my $src = ($code>>6) & 077; my $dst = $code & 077; my $src_str = regmod($src); my $dst_str = regmod($dst); return "$name $src_str,$dst_str"; } elsif ($type eq "rdst") { my $reg = ($code>>6) & 07; my $src = $code & 077; my $src_str = regmod($src); return "$name $src_str,r$reg"; } elsif ($type eq "1reg") { my $reg = $code & 07; my $reg_str = "r$reg"; $reg_str = "sp" if $reg == 6; $reg_str = "pc" if $reg == 7; return "$name $reg_str"; } elsif ($type eq "br") { # Note: in MACRO-11 syntax . refers to the address of the instruction # the opcode has offset relative to PC after instruction fetch # so 000776 --> br .-2 # 000777 --> br . # 000400 --> br .+2 # my $off = $code & 0177; my $sign = "?"; if ($code & 0200) { # negative offsets $sign = "-"; $off = ((~$off) & 0177)+1; $off = $off - 1; # refer to address of instruction } else { # positive offsets $sign = "+"; $off = $off + 1; # refer to address of instruction } return sprintf "$name .%s%o", $sign, abs(2*$off); } elsif ($type eq "sob") { # Note: like in br type instructions, asm syntax and opcode differ by one my $reg = ($code>>6) & 07; my $off = $code & 077; return sprintf "$name r%d,.-%o", $reg, 2*($off-1); } elsif ($type eq "trap") { my $off = $code & 0377; return sprintf "$name %3.3o", $off; } elsif ($type eq "spl") { my $off = $code & 07; return sprintf "$name %d", $off; } elsif ($type eq "ccop") { my $cc = $code & 017; return "nop" if ($cc == 0); return "ccc" if ($code == 0257); return "scc" if ($code == 0277); my $str = ""; my $del = ""; if ($code & 010) { $str .= $del . $name . "n", $del = "+" } if ($code & 004) { $str .= $del . $name . "z", $del = "+" } if ($code & 002) { $str .= $del . $name . "v", $del = "+" } if ($code & 001) { $str .= $del . $name . "c", $del = "+" } return $str; } elsif ($type eq "rsrc") { my $reg = ($code>>6) & 07; my $dst = $code & 077; my $dst_str = regmod($dst); return "$name r$reg,$dst_str"; } elsif ($type eq "mark") { my $off = $code & 077; return sprintf "$name %3.3o", $off; } elsif ($type eq "rfpp") { my $reg = ($code>>6) & 03; my $dst = $code & 077; my $dst_str = regmod($dst,"f"); return "$name f$reg,$dst_str"; } else { return "?type?"; } } } return "=inval="; } #------------------------------------------------------------------------------- sub regmod { my ($regmod,$pref) = @_; my $mod = ($regmod>>3) & 07; my $reg = $regmod & 07; $pref = "r" if not defined $pref or $reg>5; my $reg_str = "r$reg"; $reg_str = "sp" if $reg == 6; $reg_str = "pc" if $reg == 7; if ($mod == 0) { # mode 0: Rx { Fx for float } $reg_str = "f$reg" if defined $pref && $pref eq "f" && $reg<=5; return $reg_str; } elsif ($mod == 1) { # mode 1: (Rx) return "($reg_str)"; } elsif ($mod == 2 || $mod == 3) { # mode 2/3: (Rx)+ @(Rx)+ my $ind = ($mod == 3) ? "@" : ""; if ($reg != 7) { # if reg != pc return "$ind($reg_str)+"; } else { # if reg == pc my $str = sprintf "$ind#nnn"; # 27 -> #nnn; 37 -> @#nnn return $str; } } elsif ($mod == 4 || $mod == 5) { # mode 4/5: -(Rx) @-(Rx) my $ind = ($mod == 5) ? "@" : ""; return "$ind-($reg_str)"; } elsif ($mod == 6 || $mod == 7) { # mode 6/7: nn(Rx) @nn(Rx) my $ind = ($mod == 7) ? "@" : ""; return "${ind}nnn($reg_str)"; } } #------------------------------------------------------------------------------- sub bailout { my ($msg) = @_; print STDERR "tmuconv-F: $msg\n"; exit 1; } #------------------------------------------------------------------------------- sub print_help { print "usage: tmuconf file\n"; print " --help this message\n"; print " --dump dump all information\n"; print " --cdump dump only changes relative to prev cycle\n"; print " --t_id trace instruction decodes\n"; print " --t_ru trace register updates\n"; print " --t_em trace em transactions\n"; print " --t_ib trace ib transactions\n"; }