1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445
|
divert(-1)
dnl
dnl m4 macros for gmp assembly code, shared by all CPUs. From gmp/mpn/asm-defs.m4
dnl Copyright 1999-2006, 2011 Free Software Foundation, Inc.
dnl This file is part of the GNU MP Library.
dnl
dnl The GNU MP Library is free software; you can redistribute it and/or modify
dnl it under the terms of either:
dnl
dnl * the GNU Lesser General Public License as published by the Free
dnl Software Foundation; either version 3 of the License, or (at your
dnl option) any later version.
dnl
dnl or
dnl
dnl * the GNU General Public License as published by the Free Software
dnl Foundation; either version 2 of the License, or (at your option) any
dnl later version.
dnl
dnl or both in parallel, as here.
dnl
dnl The GNU MP Library is distributed in the hope that it will be useful, but
dnl WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
dnl or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
dnl for more details.
dnl
dnl You should have received copies of the GNU General Public License and the
dnl GNU Lesser General Public License along with the GNU MP Library. If not,
dnl see https://www.gnu.org/licenses/.
dnl These macros are designed for use with any m4 and have been used on
dnl GNU, FreeBSD, NetBSD, OpenBSD and SysV.
dnl
dnl GNU m4 and OpenBSD 2.7 m4 will give filenames and line numbers in error
dnl messages.
dnl
dnl
dnl Macros:
dnl
dnl Most new m4 specific macros have an "m4_" prefix to emphasise they're
dnl m4 expansions. But new defining things like deflit() and defreg() are
dnl named like the builtin define(), and forloop() is named following the
dnl GNU m4 example on which it's based.
dnl
dnl GNU m4 with the -P option uses "m4_" as a prefix for builtins, but that
dnl option isn't going to be used, so there's no conflict or confusion.
dnl
dnl
dnl Comments in output:
dnl
dnl The m4 comment delimiters are left at # and \n, the normal assembler
dnl commenting for most CPUs. m4 passes comment text through without
dnl expanding macros in it, which is generally a good thing since it stops
dnl unexpected expansions and possible resultant errors.
dnl
dnl But note that when a quoted string is being read, a # isn't special, so
dnl apostrophes in comments in quoted strings must be avoided or they'll be
dnl interpreted as a closing quote mark. But when the quoted text is
dnl re-read # will still act like a normal comment, suppressing macro
dnl expansion.
dnl
dnl For example,
dnl
dnl # apostrophes in comments that're outside quotes are ok
dnl # and using macro names like PROLOGUE is ok too
dnl ...
dnl ifdef(`PIC',`
dnl # but apostrophes aren't ok inside quotes
dnl # ^--wrong
dnl ...
dnl # though macro names like PROLOGUE are still ok
dnl ...
dnl ')
dnl
dnl If macro expansion in a comment is wanted, use `#' in the .asm (ie. a
dnl quoted hash symbol), which will turn into # in the .s but get
dnl expansions done on that line. This can make the .s more readable to
dnl humans, but it won't make a blind bit of difference to the assembler.
dnl
dnl All the above applies, mutatis mutandis, when changecom() is used to
dnl select @ ! ; or whatever other commenting.
dnl
dnl
dnl Variations in m4 affecting gmp:
dnl
dnl $# - When a macro is called as "foo" with no brackets, BSD m4 sets $#
dnl to 1, whereas GNU or SysV m4 set it to 0. In all cases though
dnl "foo()" sets $# to 1. This is worked around in various places.
dnl
dnl len() - When "len()" is given an empty argument, BSD m4 evaluates to
dnl nothing, whereas GNU, SysV, and the new OpenBSD, evaluate to 0.
dnl See m4_length() below which works around this.
dnl
dnl translit() - GNU m4 accepts character ranges like A-Z, and the new
dnl OpenBSD m4 does under option -g, but basic BSD and SysV don't.
dnl
dnl popdef() - in BSD and SysV m4 popdef() takes multiple arguments and
dnl pops each, but GNU m4 only takes one argument.
dnl
dnl push back - BSD m4 has some limits on the amount of text that can be
dnl pushed back. The limit is reasonably big and so long as macros
dnl don't gratuitously duplicate big arguments it isn't a problem.
dnl Normally an error message is given, but sometimes it just hangs.
dnl
dnl eval() &,|,^ - GNU and SysV m4 have bitwise operators &,|,^ available,
dnl but BSD m4 doesn't (contrary to what the man page suggests) and
dnl instead ^ is exponentiation.
dnl
dnl eval() ?: - The C ternary operator "?:" is available in BSD m4, but not
dnl in SysV or GNU m4 (as of GNU m4 1.4 and betas of 1.5).
dnl
dnl eval() -2^31 - BSD m4 has a bug where an eval() resulting in -2^31
dnl (ie. -2147483648) gives "-(". Using -2147483648 within an
dnl expression is ok, it just can't be a final result. "-(" will of
dnl course upset parsing, with all sorts of strange effects.
dnl
dnl eval() <<,>> - SysV m4 doesn't support shift operators in eval() (on
dnl Solaris 7 /usr/xpg4/m4 has them but /usr/ccs/m4 doesn't). See
dnl m4_lshift() and m4_rshift() below for workarounds.
dnl
dnl ifdef() - OSF 4.0 m4 considers a macro defined to a zero value `0' or
dnl `00' etc as not defined. See m4_ifdef below for a workaround.
dnl
dnl m4wrap() sequence - in BSD m4, m4wrap() replaces any previous m4wrap()
dnl string, in SysV m4 it appends to it, and in GNU m4 it prepends.
dnl See m4wrap_prepend() below which brings uniformity to this.
dnl
dnl m4wrap() 0xFF - old versions of BSD m4 store EOF in a C "char" under an
dnl m4wrap() and on systems where char is unsigned by default a
dnl spurious 0xFF is output. This has been observed on recent Cray
dnl Unicos Alpha, Apple MacOS X, and HPUX 11 systems. An autoconf
dnl test is used to check for this, see the m4wrap handling below. It
dnl might work to end the m4wrap string with a dnl to consume the
dnl 0xFF, but that probably induces the offending m4's to read from an
dnl already closed "FILE *", which could be bad on a glibc style
dnl stdio.
dnl
dnl __file__,__line__ - GNU m4 and OpenBSD 2.7 m4 provide these, and
dnl they're used here to make error messages more informative. GNU m4
dnl gives an unhelpful "NONE 0" in an m4wrap(), but that's worked
dnl around.
dnl
dnl __file__ quoting - OpenBSD m4, unlike GNU m4, doesn't quote the
dnl filename in __file__, so care should be taken that no macro has
dnl the same name as a file, or an unwanted expansion will occur when
dnl printing an error or warning.
dnl
dnl changecom() - BSD m4 changecom doesn't quite work like the man page
dnl suggests, in particular "changecom" or "changecom()" doesn't
dnl disable the comment feature, and multi-character comment sequences
dnl don't seem to work. If the default `#' and newline aren't
dnl suitable it's necessary to change it to something else,
dnl eg. changecom(;).
dnl
dnl OpenBSD 2.6 m4 - in this m4, eval() rejects decimal constants containing
dnl an 8 or 9, making it pretty much unusable. The bug is confined to
dnl version 2.6 (it's not in 2.5, and was fixed in 2.7).
dnl
dnl SunOS /usr/bin/m4 - this m4 lacks a number of desired features,
dnl including $# and $@, defn(), m4exit(), m4wrap(), pushdef(),
dnl popdef(). /usr/5bin/m4 is a SysV style m4 which should always be
dnl available, and "configure" will reject /usr/bin/m4 in favour of
dnl /usr/5bin/m4 (if necessary).
dnl
dnl The sparc code actually has modest m4 requirements currently and
dnl could manage with /usr/bin/m4, but there's no reason to put our
dnl macros through contortions when /usr/5bin/m4 is available or GNU
dnl m4 can be installed.
dnl --------------------------------------------------------------------------
dnl Basic error handling things.
dnl Usage: m4_dollarhash_1_if_noparen_p
dnl
dnl Expand to 1 if a call "foo" gives $# set to 1 (as opposed to 0 like GNU
dnl and SysV m4 give).
define(m4_dollarhash_1_if_noparen_test,`$#')
define(m4_dollarhash_1_if_noparen_p,
eval(m4_dollarhash_1_if_noparen_test==1))
undefine(`m4_dollarhash_1_if_noparen_test')
define(m4_error,
`errprint($@
)m4exit(1)')
dnl Usage: m4_assert_numargs(num)
dnl
dnl Put this unquoted on a line on its own at the start of a macro
dnl definition to add some code to check that num many arguments get passed
dnl to the macro. For example,
dnl
dnl define(foo,
dnl m4_assert_numargs(2)
dnl `something `$1' and `$2' blah blah')
dnl
dnl Then a call like foo(one,two,three) will provoke an error like
dnl
dnl file:10: foo expected 2 arguments, got 3 arguments
dnl
dnl Here are some calls and how many arguments they're interpreted as passing.
dnl
dnl foo(abc,def) 2
dnl foo(xyz) 1
dnl foo() 0
dnl foo -1
dnl
dnl The -1 for no parentheses at all means a macro that's meant to be used
dnl that way can be checked with m4_assert_numargs(-1). For example,
dnl
dnl define(SPECIAL_SUFFIX,
dnl m4_assert_numargs(-1)
dnl `ifdef(`FOO',`_foo',`_bar')')
dnl
dnl But as an alternative see also deflit() below where parenthesized
dnl expressions following a macro are passed through to the output.
dnl
dnl Note that in BSD m4 there's no way to differentiate calls "foo" and
dnl "foo()", so in BSD m4 the distinction between the two isn't enforced.
dnl (In GNU and SysV m4 it can be checked, and is.)
dnl m4_assert_numargs is able to check its own arguments by calling
dnl assert_numargs_internal directly.
dnl
dnl m4_doublequote($`'0) expands to ``$0'', whereas ``$`'0'' would expand
dnl to `$`'0' and do the wrong thing, and likewise for $1. The same is
dnl done in other assert macros.
dnl
dnl $`#' leaves $# in the new macro being defined, and stops # being
dnl interpreted as a comment character.
dnl
dnl `dnl ' means an explicit dnl isn't necessary when m4_assert_numargs is
dnl used. The space means that if there is a dnl it'll still work.
dnl Usage: m4_doublequote(x) expands to ``x''
define(m4_doublequote,
`m4_assert_numargs_internal(`$0',1,$#,len(`$1'))``$1''')
define(m4_assert_numargs,
`m4_assert_numargs_internal(`$0',1,$#,len(`$1'))dnl
`m4_assert_numargs_internal'(m4_doublequote($`'0),$1,$`#',`len'(m4_doublequote($`'1)))`dnl '')
dnl Called: m4_assert_numargs_internal(`macroname',wantargs,$#,len(`$1'))
define(m4_assert_numargs_internal,
`m4_assert_numargs_internal_check(`$1',`$2',m4_numargs_count(`$3',`$4'))')
dnl Called: m4_assert_numargs_internal_check(`macroname',wantargs,gotargs)
dnl
dnl If m4_dollarhash_1_if_noparen_p (BSD m4) then gotargs can be 0 when it
dnl should be -1. If wantargs is -1 but gotargs is 0 and the two can't be
dnl distinguished then it's allowed to pass.
dnl
define(m4_assert_numargs_internal_check,
`ifelse(eval($2 == $3
|| ($2==-1 && $3==0 && m4_dollarhash_1_if_noparen_p)),0,
`m4_error(`$1 expected 'm4_Narguments(`$2')`, got 'm4_Narguments(`$3')
)')')
dnl Called: m4_numargs_count($#,len(`$1'))
dnl If $#==0 then -1 args, if $#==1 but len(`$1')==0 then 0 args, otherwise
dnl $# args.
define(m4_numargs_count,
`ifelse($1,0, -1,
`ifelse(eval($1==1 && $2-0==0),1, 0, $1)')')
dnl Usage: m4_Narguments(N)
dnl "$1 argument" or "$1 arguments" with the plural according to $1.
define(m4_Narguments,
`$1 argument`'ifelse(`$1',1,,s)')
dnl --------------------------------------------------------------------------
dnl Additional error checking things.
dnl Usage: m4_assert_onearg()
dnl
dnl Put this, unquoted, at the start of a macro definition to add some code
dnl to check that one argument is passed to the macro, but with that
dnl argument allowed to be empty. For example,
dnl
dnl define(foo,
dnl m4_assert_onearg()
dnl `blah blah $1 blah blah')
dnl
dnl Calls "foo(xyz)" or "foo()" are accepted. A call "foo(xyz,abc)" fails.
dnl A call "foo" fails too, but BSD m4 can't detect this case (GNU and SysV
dnl m4 can).
define(m4_assert_onearg,
m4_assert_numargs(0)
`m4_assert_onearg_internal'(m4_doublequote($`'0),$`#')`dnl ')
dnl Called: m4_assert_onearg(`macroname',$#)
define(m4_assert_onearg_internal,
`ifelse($2,1,,
`m4_error(`$1 expected 1 argument, got 'm4_Narguments(`$2')
)')')
dnl --------------------------------------------------------------------------
dnl Various generic m4 things.
dnl Usage: m4_unquote(macro)
dnl
dnl Allow the argument text to be re-evaluated. This is useful for "token
dnl pasting" like m4_unquote(foo`'bar).
define(m4_unquote,
m4_assert_onearg()
`$1')
dnl Usage: m4_length(string)
dnl
dnl Determine the length of a string. This is the same as len(), but
dnl always expands to a number, working around the BSD len() which
dnl evaluates to nothing given an empty argument.
define(m4_length,
m4_assert_onearg()
`eval(len(`$1')-0)')
dnl Usage: m4_incr_or_decr(n,last)
dnl
dnl Do an incr(n) or decr(n), whichever is in the direction of "last".
dnl Both n and last must be numbers of course.
define(m4_incr_or_decr,
m4_assert_numargs(2)
`ifelse(eval($1<$2),1,incr($1),decr($1))')
dnl Usage: forloop(i, first, last, statement)
dnl
dnl Based on GNU m4 examples/forloop.m4, but extended.
dnl
dnl statement is expanded repeatedly, with i successively defined as
dnl
dnl first, first+1, ..., last-1, last
dnl
dnl Or if first > last, then it's
dnl
dnl first, first-1, ..., last+1, last
dnl
dnl If first == last, then one expansion is done.
dnl
dnl A pushdef/popdef of i is done to preserve any previous definition (or
dnl lack of definition). first and last are eval()ed and so can be
dnl expressions.
dnl
dnl forloop_first is defined to 1 on the first iteration, 0 on the rest.
dnl forloop_last is defined to 1 on the last iteration, 0 on the others.
dnl Nested forloops are allowed, in which case forloop_first and
dnl forloop_last apply to the innermost loop that's open.
dnl
dnl A simple example,
dnl
dnl forloop(i, 1, 2*2+1, `dnl
dnl iteration number i ... ifelse(forloop_first,1,FIRST)
dnl ')
dnl "i" and "statement" are carefully quoted, but "first" and "last" are
dnl just plain numbers once eval()ed.
define(`forloop',
m4_assert_numargs(4)
`pushdef(`$1',eval(`$2'))dnl
pushdef(`forloop_first',1)dnl
pushdef(`forloop_last',0)dnl
forloop_internal(`$1',eval(`$3'),`$4')`'dnl
popdef(`forloop_first')dnl
popdef(`forloop_last')dnl
popdef(`$1')')
dnl Called: forloop_internal(`var',last,statement)
define(`forloop_internal',
m4_assert_numargs(3)
`ifelse($1,$2,
`define(`forloop_last',1)$3',
`$3`'dnl
define(`forloop_first',0)dnl
define(`$1',m4_incr_or_decr($1,$2))dnl
forloop_internal(`$1',$2,`$3')')')
dnl Usage: deflit(name,value)
dnl
dnl Like define(), but "name" expands like a literal, rather than taking
dnl arguments. For example "name(%eax)" expands to "value(%eax)".
dnl
dnl Limitations:
dnl
dnl $ characters in the value part must have quotes to stop them looking
dnl like macro parameters. For example, deflit(reg,`123+$`'4+567'). See
dnl defreg() below for handling simple register definitions like $7 etc.
dnl
dnl "name()" is turned into "name", unfortunately. In GNU and SysV m4 an
dnl error is generated when this happens, but in BSD m4 it will happen
dnl silently. The problem is that in BSD m4 $# is 1 in both "name" or
dnl "name()", so there's no way to differentiate them. Because we want
dnl plain "name" to turn into plain "value", we end up with "name()"
dnl turning into plain "value" too.
dnl
dnl "name(foo)" will lose any whitespace after commas in "foo", for example
dnl "disp(%eax, %ecx)" would become "128(%eax,%ecx)".
dnl
dnl These parentheses oddities shouldn't matter in assembler text, but if
dnl they do the suggested workaround is to write "name ()" or "name (foo)"
dnl to stop the parentheses looking like a macro argument list. If a space
dnl isn't acceptable in the output, then write "name`'()" or "name`'(foo)".
dnl The `' is stripped when read, but again stops the parentheses looking
dnl like parameters.
dnl Quoting for deflit_emptyargcheck is similar to m4_assert_numargs. The
dnl stuff in the ifelse gives a $#, $1 and $@ evaluated in the new macro
dnl created, not in deflit.
define(deflit,
m4_assert_numargs(2)
`define(`$1',
`deflit_emptyargcheck'(``$1'',$`#',m4_doublequote($`'1))`dnl
$2`'dnl
ifelse(eval($'`#>1 || m4_length('m4_doublequote($`'1)`)!=0),1,($'`@))')')
dnl Called: deflit_emptyargcheck(macroname,$#,`$1')
define(deflit_emptyargcheck,
`ifelse(eval($2==1 && !m4_dollarhash_1_if_noparen_p && m4_length(`$3')==0),1,
`m4_error(`dont use a deflit as $1() because it loses the brackets (see deflit in asm-defs.m4 for more information)
')')')
divert`'dnl
|