mirror of
https://github.com/wfjm/w11.git
synced 2026-04-03 13:23:50 +00:00
asm-11: add limited macro support
This commit is contained in:
@@ -30,6 +30,7 @@ The full set of tests is only run for tagged releases.
|
||||
- add fast mac-only verification codes under tool/tcode, integrated with tbrun
|
||||
- add ostest support for rsx11m-31_rk, rsx11m-40_rk and rsx11mp-30_rp oskits
|
||||
- all actively used commands have now a man page
|
||||
- asm-11 has now limited macro support
|
||||
- Doxygen support now for V1.9.4; remove discontinued Tcl support
|
||||
- build flow Vivado 2022.1 ready; handle synth 8-3331 -> 8-7129 transition
|
||||
- remove Atlys support (only test designs, a w11 design was never done)
|
||||
@@ -42,6 +43,7 @@ The full set of tests is only run for tagged releases.
|
||||
- ci.yml: define TBW_GHDL_OPTS and suppress IEEE package warnings at t=0ms
|
||||
- **/tbrun.yml: since nexys4 not longer available switch to nexys4d
|
||||
- tools/bin
|
||||
- asm-11: limited macro support (.macro,.endm)
|
||||
- create_disk: -help: print byte size of disk
|
||||
- njobihtm: add -n and -h options
|
||||
- tbrun_tbwrri: fully implement --r(l|b)mon
|
||||
|
||||
76
tools/asm-11/tests/test_0300_macro.mac
Normal file
76
tools/asm-11/tests/test_0300_macro.mac
Normal file
@@ -0,0 +1,76 @@
|
||||
; $Id: test_0300_macro.mac 1262 2022-07-25 09:44:55Z mueller $
|
||||
; SPDX-License-Identifier: GPL-3.0-or-later
|
||||
; Copyright 2019- by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
|
||||
;
|
||||
; test .macro basics
|
||||
;
|
||||
.asect
|
||||
.blkw 400
|
||||
|
||||
; list macro expansion
|
||||
|
||||
.list me
|
||||
|
||||
; define and use simple macros
|
||||
|
||||
.macro scall,dst
|
||||
jsr pc,dst
|
||||
.endm
|
||||
.macro sret
|
||||
rts pc
|
||||
.endm
|
||||
.macro push,src
|
||||
mov src,-(sp)
|
||||
.endm
|
||||
.macro pop,dst
|
||||
mov (sp)+,dst
|
||||
.endm
|
||||
|
||||
t01: scall t01sub
|
||||
halt
|
||||
1$: ;;!! 001006:
|
||||
|
||||
t01sub: push r0
|
||||
push r1
|
||||
pop r1
|
||||
pop r0
|
||||
sret
|
||||
1$: ;;!! 001020:
|
||||
|
||||
; macro with defaults and auto-label
|
||||
|
||||
.macro scopy,src,dst=#t02tmp,?lbl
|
||||
mov src,r0
|
||||
mov dst,r1
|
||||
lbl: movb (r0)+,(r1)+ ;;!! 112021
|
||||
bne lbl ;;!! 001376
|
||||
.endm scopy
|
||||
|
||||
. = 02000
|
||||
t02: scopy #t02a1+<2*2>,#t02buf
|
||||
1$: ;;!! 002014:
|
||||
scopy #t02a2
|
||||
2$: ;;!! 002030:
|
||||
mov #t02a1,r5
|
||||
scopy r5
|
||||
3$: ;;!! 002046:
|
||||
;
|
||||
t02a1: .asciz /1234567890/
|
||||
t02a2: .asciz /abcdefghij/
|
||||
t02buf: .blkb 32.
|
||||
t02tmp: .blkb 32.
|
||||
|
||||
; nested macro calls
|
||||
|
||||
.macro bcopy,src,dst
|
||||
push r0
|
||||
push r1
|
||||
scopy #src,#dst
|
||||
pop r1
|
||||
pop r0
|
||||
.endm
|
||||
|
||||
. = 3000
|
||||
t03: bcopy t02a1,t02tmp
|
||||
1$: ;;!! 003024:
|
||||
.end
|
||||
367
tools/bin/asm-11
Executable file → Normal file
367
tools/bin/asm-11
Executable file → Normal file
@@ -1,19 +1,12 @@
|
||||
#!/usr/bin/perl -w
|
||||
# $Id: asm-11 1138 2019-04-26 08:14:56Z mueller $
|
||||
#
|
||||
# $Id: asm-11 1236 2022-05-14 10:11:35Z mueller $
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
# Copyright 2013-2019 by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
|
||||
#
|
||||
# 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
|
||||
# 2019-07-13 1189 1.1.1 drop superfluous exists for $opts
|
||||
# 2019-05-25 1152 1.1 add .macro,.endm,.list,.nlist
|
||||
# 2019-04-25 1138 1.0.7 print lines with errors to stderr unless -lst seen
|
||||
# 2019-04-19 1133 1.0.6 .end directive autocreates '...end' label
|
||||
# 2018-11-03 1065 1.0.5 add and use bailout
|
||||
@@ -35,6 +28,7 @@ use Getopt::Long;
|
||||
|
||||
use constant TMASK_STRING => 0x0001;
|
||||
use constant TMASK_STRINGEXP => 0x0002;
|
||||
use constant TMASK_MACROARG => 0x0004;
|
||||
|
||||
my %opts = ();
|
||||
|
||||
@@ -66,6 +60,10 @@ my %pst = (
|
||||
'.even' => {typ=>'dir'}, #
|
||||
'.odd' => {typ=>'dir'}, #
|
||||
'.asect' => {typ=>'dir'}, #
|
||||
'.macro' => {typ=>'dir'}, #
|
||||
'.endm' => {typ=>'dir'}, #
|
||||
'.list' => {typ=>'dir'}, #
|
||||
'.nlist' => {typ=>'dir'}, #
|
||||
'.end' => {typ=>'dir'}, #
|
||||
#register defs
|
||||
'r0' => {typ=>'reg', val=>0},
|
||||
@@ -253,6 +251,9 @@ my $llbl_ascope = 0; # annonymous local label scope count
|
||||
|
||||
# macro table
|
||||
my %mst;
|
||||
my $mdefnam; # macro currently being defined
|
||||
my @mdefstk; # open .macro,.rept defs stack
|
||||
my $mautolbl = 30000; # auto-generated label
|
||||
|
||||
my @flist; # list of filenames
|
||||
my $fstem; # stem or last file name
|
||||
@@ -278,7 +279,7 @@ my @out_data; # output data
|
||||
|
||||
autoflush STDOUT 1 if (-p STDOUT); # autoflush if output into pipe
|
||||
|
||||
if (exists $opts{help}) {
|
||||
if ($opts{help}) {
|
||||
print_help();
|
||||
exit 0;
|
||||
}
|
||||
@@ -384,24 +385,7 @@ sub read_file {
|
||||
chomp;
|
||||
my $line = $_;
|
||||
$lineno += 1;
|
||||
my $rl = parse_line($fileno, $lineno, $line);
|
||||
dump_rl($rl) if $opts{tpass1};
|
||||
push @src, $rl;
|
||||
|
||||
# handle .include
|
||||
if (defined $$rl{oper} && $$rl{oper} eq '.include' && defined $$rl{ifile}) {
|
||||
my $fnam = $$rl{ifile};
|
||||
unless ($fnam =~ m|^/|) {
|
||||
foreach (@{$opts{I}}) {
|
||||
if (-r "$_/$fnam") {
|
||||
$fnam = "$_/$fnam";
|
||||
last;
|
||||
}
|
||||
}
|
||||
}
|
||||
read_file($fnam);
|
||||
}
|
||||
|
||||
pass1_line($fileno, $lineno, $line);
|
||||
}
|
||||
|
||||
return;
|
||||
@@ -409,6 +393,57 @@ sub read_file {
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
sub exec_macro {
|
||||
my ($rmexec) = @_;
|
||||
my $mname = $rmexec->{name};
|
||||
foreach my $rmline (@{$mst{$mname}{body}}) {
|
||||
my $lrest = $rmline->{line};
|
||||
my $fileno = $rmline->{fileno};
|
||||
my $lineno = $rmline->{lineno};
|
||||
my $line = '';
|
||||
while ($lrest =~ m/([a-zA-Z\$\.][a-zA-Z0-9\$\.]*)/) {
|
||||
$line .= $`;
|
||||
$line .= (defined $rmexec->{vals}{$1}) ? $rmexec->{vals}{$1} : $1;
|
||||
$lrest = $';
|
||||
}
|
||||
$line .= $lrest;
|
||||
pass1_line($fileno, $lineno, $line);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
sub pass1_line {
|
||||
my ($fileno,$lineno,$line) = @_;
|
||||
|
||||
my $rl = parse_line($fileno, $lineno, $line);
|
||||
dump_rl($rl) if $opts{tpass1};
|
||||
push @src, $rl;
|
||||
|
||||
# handle .include
|
||||
if (defined $$rl{oper} && $$rl{oper} eq '.include' && defined $$rl{ifile}) {
|
||||
my $fnam = $$rl{ifile};
|
||||
unless ($fnam =~ m|^/|) {
|
||||
foreach (@{$opts{I}}) {
|
||||
if (-r "$_/$fnam") {
|
||||
$fnam = "$_/$fnam";
|
||||
last;
|
||||
}
|
||||
}
|
||||
}
|
||||
read_file($fnam);
|
||||
}
|
||||
|
||||
# handle macro expansions
|
||||
if (defined $$rl{oper} && defined $$rl{mexec}) {
|
||||
exec_macro($$rl{mexec});
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
sub parse_line {
|
||||
my ($fileno,$lineno,$line) = @_;
|
||||
|
||||
@@ -466,9 +501,45 @@ sub parse_line {
|
||||
}
|
||||
}
|
||||
|
||||
if (defined $mdefnam) { # handle .macro,... definitions
|
||||
my $ltrim = $line;
|
||||
my $mdefend;
|
||||
$ltrim =~ s/^[a-zA-Z\$\.][a-zA-Z0-9\$\.]*://; # trim label
|
||||
$ltrim =~ s/^[0-9]+\$]://; # trim local label
|
||||
$ltrim =~ s/^\s*//; # trim leading white
|
||||
if ($ltrim =~ m/^(\.[a-zA-Z\$\.][a-zA-Z0-9\$\.]*)/) { # directive seen
|
||||
my $dnam = $1;
|
||||
if ($dnam =~ m/^\.(macro|rept)/) { # nested .macro etc seen
|
||||
push @mdefstk, $dnam;
|
||||
} elsif ($dnam =~ m/^\.(endm|endr)/) { # .endm or .endr seen
|
||||
if (scalar(@mdefstk) > 1) {
|
||||
pop @mdefstk;
|
||||
} else {
|
||||
$mdefend = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
unless ($mdefend) {
|
||||
push @{$mst{$mdefnam}{body}}, {line => $l{line},
|
||||
fileno => $l{fileno},
|
||||
lineno => $l{lineno}
|
||||
};
|
||||
return \%l;
|
||||
}
|
||||
}
|
||||
|
||||
while (1) {
|
||||
if ($opts{tparse}) {
|
||||
printf "-- state = $state";
|
||||
printf "-- state = %-8s",$state;
|
||||
my $rest = '';
|
||||
foreach my $t (@t_pushback) { $rest .= $t->{val} if defined $t->{val}; }
|
||||
foreach my $c (@{$l{cl}}) { $rest .= $c; }
|
||||
$rest =~ s/\s+/ /g;
|
||||
if (length($rest)>17) {
|
||||
$rest = substr($rest,0,17) . '...';
|
||||
}
|
||||
while (length($rest) < 20) { $rest .= ' ' }
|
||||
printf "@ \"%s\"", $rest;
|
||||
printf ", nest = %d", scalar(@e_pbeg) if $state =~ m/^e_/;
|
||||
print "\n";
|
||||
}
|
||||
@@ -485,6 +556,9 @@ sub parse_line {
|
||||
# directive name seen ?
|
||||
if (exists $pst{$$rt{val}} && $pst{$$rt{val}}{typ} eq 'dir') {
|
||||
$state = 'oper';
|
||||
# macro name seen ?
|
||||
} elsif (exists $mst{$$rt{val}}) {
|
||||
$state = 'oper';
|
||||
|
||||
# otherwise check for label or assignment
|
||||
} else {
|
||||
@@ -520,7 +594,7 @@ sub parse_line {
|
||||
}
|
||||
}
|
||||
|
||||
# anything else seen, treat a implicit .word
|
||||
# anything else seen, treat as implicit .word
|
||||
} else {
|
||||
pushback_token(\%l);
|
||||
$state = 'iword';
|
||||
@@ -546,21 +620,21 @@ sub parse_line {
|
||||
my $rs = $pst{$op};
|
||||
if ($$rs{typ} eq 'dir') { # directives ------------------
|
||||
$d_dire = $op;
|
||||
if ($op eq '.word' || # .word
|
||||
$op eq '.byte') { # .byte
|
||||
if ($op eq '.word' || # .word ----------------
|
||||
$op eq '.byte') { # .byte ----------------
|
||||
$state = 'dl_beg';
|
||||
|
||||
} elsif ($op eq '.blkw' || # .blkw
|
||||
$op eq '.blkb') { # .blkb
|
||||
} elsif ($op eq '.blkw' || # .blkw ----------------
|
||||
$op eq '.blkb') { # .blkb ----------------
|
||||
$state = 'dl_beg';
|
||||
|
||||
} elsif ($op eq '.ascii' || # .ascii
|
||||
$op eq '.asciz') { # .asciz
|
||||
} elsif ($op eq '.ascii' || # .ascii ---------------
|
||||
$op eq '.asciz') { # .asciz ---------------
|
||||
$tmask = TMASK_STRING;
|
||||
$state = 'al_next';
|
||||
|
||||
} elsif ($op eq '.even' || # .even
|
||||
$op eq '.odd') { # .odd
|
||||
} elsif ($op eq '.even' || # .even ----------------
|
||||
$op eq '.odd') { # .odd -----------------
|
||||
my $dot = getdot();
|
||||
my $inc = 0;
|
||||
$inc = 1 if $op eq '.even' && ($dot&01)==1;
|
||||
@@ -571,12 +645,12 @@ sub parse_line {
|
||||
$l{lstdot} = 1;
|
||||
$state = 'end';
|
||||
|
||||
} elsif ($op eq '.asect') { # .asect
|
||||
} elsif ($op eq '.asect') { # .asect ---------------
|
||||
# .asect is currently a noop because asect is start default
|
||||
$l{lstdot} = 1;
|
||||
$state = 'end';
|
||||
|
||||
} elsif ($op eq '.include') { # .include
|
||||
} elsif ($op eq '.include') { # .include -------------
|
||||
$rt = get_token(\%l, TMASK_STRING);
|
||||
if ($$rt{tag} eq 'STR') {
|
||||
my $ifile = $$rt{val};
|
||||
@@ -591,7 +665,82 @@ sub parse_line {
|
||||
$state = 'q';
|
||||
}
|
||||
|
||||
} elsif ($op eq '.end') { # .end
|
||||
} elsif ($op eq '.macro') { # .macro ---------------
|
||||
$rt = get_token(\%l, $tmask);
|
||||
if ($$rt{tag} eq 'SYM') {
|
||||
$mdefnam = $$rt{val};
|
||||
$mst{$mdefnam} = {name => $mdefnam,
|
||||
typ => '.macro',
|
||||
args => [],
|
||||
body => []
|
||||
};
|
||||
my $mod;
|
||||
$state = 'end';
|
||||
while (1) { # loop over argument definitions
|
||||
$rt = get_token(\%l, TMASK_MACROARG);
|
||||
last if $$rt{tag} eq 'EOL';
|
||||
next if $$rt{tag} eq 'DEL'; # FIXME_code: that's likely not OK
|
||||
if ($$rt{tag} eq 'MMOD') { # modifier seen ?
|
||||
$mod = $$rt{val};
|
||||
$rt = get_token(\%l, TMASK_MACROARG);
|
||||
if ($$rt{tag} eq 'SYM') { # ensure next token is symbol
|
||||
pushback_token(\%l);
|
||||
next;
|
||||
} else {
|
||||
$state = 'q';
|
||||
last;
|
||||
}
|
||||
}
|
||||
if ($$rt{tag} eq 'SYM') { # key name seen
|
||||
my $key = $$rt{val};
|
||||
my $val;
|
||||
$rt = get_token(\%l, TMASK_MACROARG);
|
||||
if ($$rt{tag} eq 'ASS') { # is it key=val pair ?
|
||||
$rt = get_token(\%l, TMASK_MACROARG);
|
||||
if ($$rt{tag} eq 'SYM' || $$rt{tag} eq 'MVAL') {
|
||||
$val = $$rt{val};
|
||||
} elsif ($$rt{tag} eq 'DEL' || $$rt{tag} eq 'EOL') {
|
||||
$val = '';
|
||||
} else {
|
||||
$state = 'q';
|
||||
last;
|
||||
}
|
||||
} else {
|
||||
pushback_token(\%l);
|
||||
}
|
||||
push @{$mst{$mdefnam}{args}}, {key => $key,
|
||||
val => $val,
|
||||
mod => $mod
|
||||
};
|
||||
} else {
|
||||
$state = 'q';
|
||||
last;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$state = 'q';
|
||||
}
|
||||
|
||||
} elsif ($op eq '.endm') { # .endm ----------------
|
||||
$rt = get_token(\%l, $tmask);
|
||||
if ($$rt{tag} eq 'EOL' || $$rt{tag} eq 'SYM') {
|
||||
add_err(\%l, 'A') if $$rt{tag} eq 'SYM' && $$rt{val} ne $mdefnam;
|
||||
$mdefnam = undef;
|
||||
$state = 'end';
|
||||
} else {
|
||||
$state = 'q';
|
||||
}
|
||||
|
||||
} elsif ($op eq '.list' || # .list ----------------
|
||||
$op eq '.nlist') { # .nlist ---------------
|
||||
while (1) { # loop over options
|
||||
$rt = get_token(\%l, $tmask);
|
||||
last if $$rt{tag} eq 'EOL';
|
||||
next if $$rt{tag} eq 'DEL'; # FIXME_code: check delimiter
|
||||
# FIXME_code: handle .list/.nlist
|
||||
}
|
||||
$state = 'end';
|
||||
} elsif ($op eq '.end') { # .end -----------------
|
||||
$state = 'dl_beg';
|
||||
|
||||
} else {
|
||||
@@ -621,8 +770,41 @@ sub parse_line {
|
||||
}
|
||||
|
||||
}
|
||||
} else { # oper noy in pst --> implicit .word
|
||||
pushback_token(\%l);
|
||||
|
||||
} elsif (exists $mst{$op}) { # op in mst -> expand macro ---
|
||||
my %mexec = (name => $op,
|
||||
keys => [],
|
||||
vals => {}
|
||||
);
|
||||
foreach my $marg (@{$mst{$op}{args}}) {
|
||||
push @{$mexec{keys}}, $marg->{key};
|
||||
$mexec{vals}{$marg->{key}} = $marg->{val}; # set defaults
|
||||
}
|
||||
my $iarg = 0;
|
||||
while (1) {
|
||||
$rt = get_token(\%l, TMASK_MACROARG);
|
||||
last if $$rt{tag} eq 'EOL';
|
||||
next if $$rt{tag} eq 'DEL'; # FIXME_code: that's for sure not OK
|
||||
if ($$rt{tag} eq 'SYM' || $$rt{tag} eq 'MVAL' ||
|
||||
$$rt{tag} eq 'MSTR') {
|
||||
my $key = $mexec{keys}[$iarg]; # FIXME_code: check valid index !
|
||||
my $val = $$rt{val}; # FIXME_code: strip <> or ^// !
|
||||
$mexec{vals}{$key} = $val;
|
||||
$iarg += 1;
|
||||
}
|
||||
}
|
||||
# finally setup auto-generated labels
|
||||
foreach my $marg (@{$mst{$op}{args}}) {
|
||||
next unless defined $marg->{mod} && $marg->{mod} eq '?';
|
||||
my $key = $marg->{key};
|
||||
next if defined $mexec{vals}{$key} && $mexec{vals}{$key} ne '';
|
||||
$mexec{vals}{$key} = sprintf '%5d$', $mautolbl++;
|
||||
}
|
||||
$l{mexec} = \%mexec;
|
||||
$state = 'end';
|
||||
|
||||
} else { # oper not in pst and mst -----
|
||||
pushback_token(\%l); # --> implicit .word
|
||||
$state = 'iword';
|
||||
}
|
||||
|
||||
@@ -1416,11 +1598,60 @@ sub get_token1 {
|
||||
$str .= $c;
|
||||
return finish_token(\%t, tag=> 'STR', val=> $str) if $c eq $del;
|
||||
}
|
||||
add_err($rl, 'A');
|
||||
add_err($rl, 'A'); # indeed 'A' error, not 'Q' !!
|
||||
return finish_token(\%t, tag=> 'STR', val=> $str);
|
||||
}
|
||||
}
|
||||
|
||||
if ($tmask & TMASK_MACROARG) {
|
||||
if ($c eq '<' || $c eq '^') { # <...> and ^/..../
|
||||
my $del = shift @$rcl;
|
||||
my $str = $del;
|
||||
if ($del eq '^') {
|
||||
$del = shift @$rcl;
|
||||
if (not defined $del) {
|
||||
add_err($rl, 'A');
|
||||
return finish_token(\%t, tag=> 'MSTR', val=> $str);
|
||||
}
|
||||
$str .= $del;
|
||||
}
|
||||
while (scalar(@$rcl)) {
|
||||
my $c = shift @$rcl;
|
||||
$str .= $c;
|
||||
return finish_token(\%t, tag=> 'MSTR', val=> $str) if $c eq $del;
|
||||
}
|
||||
add_err($rl, 'A');
|
||||
return finish_token(\%t, tag=> 'MSTR', val=> $str);
|
||||
} elsif ($c =~ m/[a-zA-Z\$\.]/) { # symbol names
|
||||
while (scalar(@$rcl)) {
|
||||
last if ($$rcl[0] !~ m/[a-zA-Z0-9\$\.]/);
|
||||
$val .= shift @$rcl;
|
||||
}
|
||||
if ((not defined $$rcl[0]) || $$rcl[0]=~ m/(\s|=|,|;)/) { # delimiter seen
|
||||
return finish_token(\%t, tag=> 'SYM', val=> $val); # it's a symbol
|
||||
} else { # else swallow rest
|
||||
while (scalar(@$rcl)) {
|
||||
last if $$rcl[0] =~ m/(\s|,|;)/; # stop at white, comma, comment
|
||||
$val .= shift @$rcl;
|
||||
}
|
||||
return finish_token(\%t, tag=> 'MVAL', val=> $val);
|
||||
}
|
||||
} elsif ($c eq '?' || $c eq '\\') { # ? or \ modifiers
|
||||
return finish_token(\%t, tag=> 'MMOD', val=> shift @$rcl);
|
||||
} elsif ($c eq '=') { # = key/val
|
||||
return finish_token(\%t, tag=> 'ASS', val=> shift @$rcl);
|
||||
} elsif ($c eq ',') { # ' seperator
|
||||
return finish_token(\%t, tag=> 'DEL', val=> shift @$rcl);
|
||||
} else {
|
||||
$val = shift @$rcl;
|
||||
while (scalar(@$rcl)) {
|
||||
last if $$rcl[0] =~ m/(\s|,|;)/; # stop at white, comma, comment
|
||||
$val .= shift @$rcl;
|
||||
}
|
||||
return finish_token(\%t, tag=> 'MVAL', val=> $val);
|
||||
}
|
||||
}
|
||||
|
||||
# looks like symbol ?
|
||||
if ($c =~ m/[a-zA-Z\$\.]/) {
|
||||
while (scalar(@$rcl)) {
|
||||
@@ -2317,7 +2548,7 @@ sub dump_rl {
|
||||
}
|
||||
}
|
||||
if (defined $$rl{opcode}) {
|
||||
printf " code: %6.6o,fmt=%-2s", $$rl{opcode}, $$rl{opfmt};
|
||||
printf " code : %6.6o,fmt=%-2s", $$rl{opcode}, $$rl{opfmt};
|
||||
if (defined $$rl{o1mod}) {
|
||||
printf ", o1=%s%s", $$rl{o1mod},$$rl{o1reg};
|
||||
printf ",ei=%d:%d,val=%s", $$rl{o1ebeg}, $$rl{o1eend},
|
||||
@@ -2336,17 +2567,31 @@ sub dump_rl {
|
||||
print "\n";
|
||||
}
|
||||
if (scalar(@{$$rl{outw}})) {
|
||||
print " outw:";
|
||||
print " outw :";
|
||||
foreach (@{$$rl{outw}}) { printf " %6.6o", $_; }
|
||||
print "\n";
|
||||
}
|
||||
if (scalar(@{$$rl{outb}})) {
|
||||
print " outb:";
|
||||
print " outb :";
|
||||
foreach (@{$$rl{outb}}) { printf " %3.3o", $_; }
|
||||
print "\n";
|
||||
}
|
||||
if (defined $$rl{cl}) {
|
||||
my $str = join '',@{$$rl{cl}};
|
||||
print " cl : $str\n" if length($str);
|
||||
}
|
||||
if (defined $$rl{mexec}) {
|
||||
printf " mexec : %-6s : ", $$rl{mexec}{name};
|
||||
my $del = '';
|
||||
foreach my $key (@{$$rl{mexec}{keys}}) {
|
||||
printf '%s%s', $del,$key;
|
||||
printf '=%s', $$rl{mexec}{vals}{$key} if defined $$rl{mexec}{vals}{$key};
|
||||
$del = ',';
|
||||
}
|
||||
printf "\n";
|
||||
}
|
||||
foreach my $key (sort keys %{$rl}) {
|
||||
next if $key =~ m/^(line|err|typ|oper|lineno|psect|dot|opcode|opfmt|o[12](mod|reg|ebeg|eend)|ebeg|eend|tl|delist|outw|outb)$/;
|
||||
next if $key =~ m/^(line|err|typ|oper|lineno|psect|dot|opcode|opfmt|o[12](mod|reg|ebeg|eend)|ebeg|eend|tl|delist|outw|outb|cl|mexec)$/;
|
||||
printf " %-6s: %s\n", $key, savestr($$rl{$key});
|
||||
}
|
||||
return;
|
||||
@@ -2377,6 +2622,26 @@ sub dump_sym {
|
||||
$lst{$key}{psect}, save66o($lst{$key}{val});
|
||||
}
|
||||
|
||||
my @mlist = sort keys %mst;
|
||||
if (scalar @mlist) {
|
||||
print "\n";
|
||||
print "macro typ body argument-list\n";
|
||||
print "------ ------ ---- -------------\n";
|
||||
foreach my $mnam (@mlist) {
|
||||
printf '%-6s %-6s %4d ', $mnam,
|
||||
$mst{$mnam}{typ}, scalar(@{$mst{$mnam}{body}});
|
||||
my $del = '';
|
||||
foreach my $arg (@{$mst{$mnam}{args}}) {
|
||||
printf '%s', $del;
|
||||
printf '%s',$arg->{mod} if defined $arg->{mod};
|
||||
printf '%s',$arg->{key};
|
||||
printf '=%s',$arg->{val} if defined $arg->{val};
|
||||
$del = ',';
|
||||
}
|
||||
print "\n";
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2436,7 +2701,7 @@ sub print_help {
|
||||
print " --lst create listing (default file name)\n";
|
||||
print " --olst=fnam create listing (concrete file name)\n";
|
||||
print " --lda create absolute loader output (default file name)\n";
|
||||
print " --olda create absolute loader output (concrete file name)\n";
|
||||
print " --olda=fnam create absolute loader output (concrete file name)\n";
|
||||
print " --cof create compound output (default file name)\n";
|
||||
print " --ocof=fnam create compound output (concrete file name)\n";
|
||||
print " --lsm create lsmem style memory dump (default file name)\n";
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
.\" -*- nroff -*-
|
||||
.\" $Id: asm-11.1 1237 2022-05-15 07:51:47Z mueller $
|
||||
.\" $Id: asm-11.1 1262 2022-07-25 09:44:55Z mueller $
|
||||
.\" SPDX-License-Identifier: GPL-3.0-or-later
|
||||
.\" Copyright 2013-2022 by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
|
||||
.\"
|
||||
.\" ------------------------------------------------------------------
|
||||
.
|
||||
.TH ASM-11 1 2019-04-19 "Retro Project" "Retro Project Manual"
|
||||
.TH ASM-11 1 2019-05-25 "Retro Project" "Retro Project Manual"
|
||||
.\" ------------------------------------------------------------------
|
||||
.SH NAME
|
||||
asm-11 \- simple assembler for MACRO-11 style PDP-11 code
|
||||
@@ -61,13 +61,36 @@ Activated with the \fB\-\-lst\fP or \fB\-\-olst\fP options.
|
||||
.blkw allocate words of storage
|
||||
.byte store bytes of data
|
||||
.end end of source
|
||||
.endm end of macro
|
||||
.even ensure word aligment
|
||||
.include include another source file
|
||||
.list parsed but otherwise ignored; me always enabled
|
||||
.nlist parsed but otherwise ignored
|
||||
.macro subset of macro functionality
|
||||
.odd align to odd byte address
|
||||
.word store words of data
|
||||
.EE
|
||||
|
||||
and thus neither macro, nor conditional assembly, nor psect support.
|
||||
and thus restricted macro support and neither conditional assembly,
|
||||
nor psect support.
|
||||
.
|
||||
.SS Level of macro support
|
||||
Enough for simple macros and useful for writing test benches.
|
||||
Auto-labels are supported (?name syntax). Main limitations:
|
||||
.RS 2
|
||||
.PD 0
|
||||
.IP "-" 2
|
||||
no \\var support (pass by value)
|
||||
.IP "-"
|
||||
only positional parameters
|
||||
.IP "-"
|
||||
no concatination support
|
||||
.IP "-"
|
||||
no .mexit, .mdelete, .mcall support
|
||||
.PD
|
||||
.RE
|
||||
.PP
|
||||
|
||||
.
|
||||
.\" ------------------------------------------------------------------
|
||||
.SH OPTIONS
|
||||
|
||||
Reference in New Issue
Block a user